JavaScript 中的类与静态方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7694501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Class vs. static method in JavaScript
提问by lostyzd
I know this will work:
我知道这会起作用:
function Foo() {};
Foo.prototype.talk = function () {
alert('hello~\n');
};
var a = new Foo;
a.talk(); // 'hello~\n'
But if I want to call
但如果我想打电话
Foo.talk() // this will not work
Foo.prototype.talk() // this works correctly
I find some methods to make Foo.talk
work,
我找到了一些Foo.talk
工作的方法,
Foo.__proto__ = Foo.prototype
Foo.talk = Foo.prototype.talk
Foo.__proto__ = Foo.prototype
Foo.talk = Foo.prototype.talk
Are there other ways to do this? I don't know whether it is right to do so. Do you use class methods or static methods in your JavaScript code?
还有其他方法可以做到这一点吗?我不知道这样做是否正确。您在 JavaScript 代码中使用类方法还是静态方法?
回答by zzzzBov
First off, remember that JavaScript is primarily a prototypal language, rather than a class-based language1. Foo
isn't a class, it's a function, which is an object. You can instantiate an object fromthat function using the new
keyword which will allow you to create something similar to a class in a standard OOP language.
首先,请记住 JavaScript 主要是一种原型语言,而不是基于类的语言1。Foo
不是一个类,它是一个函数,它是一个对象。您可以使用关键字从该函数实例化一个对象,new
这将允许您创建类似于标准 OOP 语言中的类的东西。
I'd suggest ignoring __proto__
most of the time because it has poor cross browser support, and instead focus on learning about how prototype
works.
我建议__proto__
大多数时候忽略它,因为它的跨浏览器支持很差,而是专注于了解prototype
工作原理。
If you have an instance of an object created from a function2and you access one of its members (methods, attributes, properties, constants etc) in any way, the access will flow down the prototype hierarchy until it either (a) finds the member, or (b) doesn't find another prototype.
如果您有一个从函数2创建的对象实例,并且您以任何方式访问其成员之一(方法、属性、属性、常量等),则访问将沿着原型层次向下流动,直到它 (a) 找到成员,或 (b) 没有找到另一个原型。
The hierarchy starts on the object that was called, and then searches its prototype object. If the prototype object has a prototype, it repeats, if no prototype exists, undefined
is returned.
层次结构从被调用的对象开始,然后搜索其原型对象。如果原型对象有原型,则重复,如果不存在原型,undefined
则返回。
For example:
例如:
foo = {bar: 'baz'};
console.log(foo.bar); // logs "baz"
foo = {};
console.log(foo.bar); // logs undefined
function Foo(){}
Foo.prototype = {bar: 'baz'};
f = new Foo();
console.log(f.bar);
// logs "baz" because the object f doesn't have an attribute "bar"
// so it checks the prototype
f.bar = 'buzz';
console.log( f.bar ); // logs "buzz" because f has an attribute "bar" set
It looks to me like you've at least somewhat understood these "basic" parts already, but I need to make them explicit just to be sure.
在我看来,您至少已经对这些“基本”部分有所了解,但为了确定起见,我需要将它们明确化。
In JavaScript, everything is an object3.
在 JavaScript 中,一切都是对象3。
everythingis an object.
一切都是对象。
function Foo(){}
doesn't just define a new function, it defines a new function object that can be accessed using Foo
.
function Foo(){}
不只是定义一个新函数,它还定义了一个可以使用Foo
.
This is why you can access Foo
's prototype with Foo.prototype
.
这就是为什么您可以使用 访问Foo
的原型Foo.prototype
。
What you can also do is set more functionson Foo
:
你也可以做的是设置更多的功能上Foo
:
Foo.talk = function () {
alert('hello world!');
};
This new function can be accessed using:
可以使用以下方法访问此新功能:
Foo.talk();
I hope by now you're noticing a similarity between functions on a function object and a static method.
我希望现在您已经注意到函数对象上的函数和静态方法之间的相似性。
Think of f = new Foo();
as creating a class instance, Foo.prototype.bar = function(){...}
as defining a shared method for the class, and Foo.baz = function(){...}
as defining a public static method for the class.
可以将其f = new Foo();
视为创建类实例、Foo.prototype.bar = function(){...}
为类定义共享方法以及为类Foo.baz = function(){...}
定义公共静态方法。
ECMAScript 2015 introduced a variety of syntactic sugar for these sorts of declarations to make them simpler to implement while also being easier to read. The previous example can therefore be written as:
ECMAScript 2015 为这些类型的声明引入了各种语法糖,使它们更易于实现,同时也更易于阅读。因此,前面的例子可以写成:
class Foo {
bar() {...}
static baz() {...}
}
which allows bar
to be called as:
这允许bar
被称为:
const f = new Foo()
f.bar()
and baz
to be called as:
并被baz
称为:
Foo.baz()
1: class
was a "Future Reserved Word" in the ECMAScript 5 specification, but ES6 introduces the ability to define classes using the class
keyword.
1:class
是 ECMAScript 5 规范中的“未来保留字”,但 ES6 引入了使用class
关键字定义类的能力。
2: essentially a class instance created by a constructor, but there are many nuanced differences that I don't want to mislead you
2:本质上是一个由构造函数创建的类实例,但是有很多细微差别我不想误导你
3: primitive values—which include undefined
, null
, booleans, numbers, and strings—aren't technically objects because they're low-level language implementations. Booleans, numbers, and strings still interact with the prototype chain as though they were objects, so for the purposes of this answer, it's easier to consider them "objects" even though they're not quite.
3:原始值——包括undefined
、null
、布尔值、数字和字符串——在技术上不是对象,因为它们是低级语言实现。布尔值、数字和字符串仍然像对象一样与原型链交互,因此就本答案而言,即使它们不完全是“对象”,也更容易将它们视为“对象”。
回答by Bipul
You can achieve it as below:
你可以实现它如下:
function Foo() {};
Foo.talk = function() { alert('I am talking.'); };
You can now invoke "talk" function as below:
您现在可以调用“talk”功能,如下所示:
Foo.talk();
You can do this because in JavaScript, functions are objects as well.
您可以这样做,因为在 JavaScript 中,函数也是对象。
回答by Eduardo Cuomo
Call a static method from an instance:
从实例调用静态方法:
function Clazz() {};
Clazz.staticMethod = function() {
alert('STATIC!!!');
};
Clazz.prototype.func = function() {
this.constructor.staticMethod();
}
var obj = new Clazz();
obj.func(); // <- Alert's "STATIC!!!"
Simple Javascript Class Project: https://github.com/reduardo7/sjsClass
简单的Javascript类项目:https: //github.com/redardo7/sjsClass
回答by Jaskey
Here is a good example to demonstrate how Javascript works with static/instance variables and methods.
这是一个很好的例子来演示 Javascript 如何与静态/实例变量和方法一起工作。
function Animal(name) {
Animal.count = Animal.count+1||1;// static variables, use function name "Animal"
this.name = name; //instance variable, using "this"
}
Animal.showCount = function () {//static method
alert(Animal.count)
}
Animal.prototype.showName=function(){//instance method
alert(this.name);
}
var mouse = new Animal("Mickey");
var elephant = new Animal("Haddoop");
Animal.showCount(); // static method, count=2
mouse.showName();//instance method, alert "Mickey"
mouse.showCount();//Error!! mouse.showCount is not a function, which is different from Java
回答by Dima Fomin
In additions, now it is possible to do with class
and static
此外,现在可以使用class
和static
'use strict'
class Foo {
static talk() {
console.log('talk')
};
speak() {
console.log('speak')
};
};
will give
会给
var a = new Foo();
Foo.talk(); // 'talk'
a.talk(); // err 'is not a function'
a.speak(); // 'speak'
Foo.speak(); // err 'is not a function'
回答by A-Sharabiani
I use namespaces:
我使用命名空间:
var Foo = {
element: document.getElementById("id-here"),
Talk: function(message) {
alert("talking..." + message);
},
ChangeElement: function() {
this.element.style.color = "red";
}
};
And to use it:
并使用它:
Foo.Talk("Testing");
Or
或者
Foo.ChangeElement();
回答by Abdennour TOUMI
ES6 supports now class
& static
keywords like a charm :
ES6 支持 now class
&static
关键字之类的魅力:
class Foo {
constructor() {}
talk() {
console.log("i am not static");
}
static saying() {
console.log(this.speech);
}
static get speech() {
return "i am static method";
}
}
回答by Combine
If you have to write static methods in ES5 I found a great tutorial for that:
如果您必须在 ES5 中编写静态方法,我找到了一个很棒的教程:
//Constructor
var Person = function (name, age){
//private properties
var priv = {};
//Public properties
this.name = name;
this.age = age;
//Public methods
this.sayHi = function(){
alert('hello');
}
}
// A static method; this method only
// exists on the class and doesn't exist
// on child objects
Person.sayName = function() {
alert("I am a Person object ;)");
};
see @https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/
见@ https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/
回答by ngakak
Just additional notes. Using class ES6, When we create static methods..the Javacsript engine set the descriptor attribute a lil bit different from the old-school "static" method
只是补充说明。使用 ES6 类,当我们创建静态方法时……Javacsript 引擎将描述符属性设置为与旧式“静态”方法略有不同
function Car() {
}
Car.brand = function() {
console.log('Honda');
}
console.log(
Object.getOwnPropertyDescriptors(Car)
);
it sets internal attribute (descriptor property) for brand() to
它将brand() 的内部属性(描述符属性)设置为
..
brand: [object Object] {
configurable: true,
enumerable: true,
value: ..
writable: true
}
..
compared to
相比
class Car2 {
static brand() {
console.log('Honda');
}
}
console.log(
Object.getOwnPropertyDescriptors(Car2)
);
that sets internal attribute for brand() to
将brand()的内部属性设置为
..
brand: [object Object] {
configurable: true,
enumerable: false,
value:..
writable: true
}
..
see that enumerableis set to falsefor static method in ES6.
看到在 ES6 中,静态方法的enumerable设置为false。
it means you cant use the for-in loop to check the object
这意味着您不能使用 for-in 循环来检查对象
for (let prop in Car) {
console.log(prop); // brand
}
for (let prop in Car2) {
console.log(prop); // nothing here
}
static method in ES6 is treated like other's class private property (name, length, constructor) except that static method is still writable thus the descriptor writableis set to true{ writable: true }
. it also means that we can override it
ES6 中的静态方法被视为其他类的私有属性(名称、长度、构造函数),除了静态方法仍然是可写的,因此描述符writable被设置为true{ writable: true }
。这也意味着我们可以覆盖它
Car2.brand = function() {
console.log('Toyota');
};
console.log(
Car2.brand() // is now changed to toyota
);
回答by Dave Keane
Static method calls are made directly on the class and are not callable on instances of the class. Static methods are often used to create utility function
静态方法调用直接在类上进行,不能在类的实例上调用。静态方法通常用于创建效用函数
Pretty clear description
描述很清楚
Taken Directly from mozilla.org
Foo needs to be bound to your class Then when you create a new instance you can call myNewInstance.foo() If you import your class you can call a static method
Foo 需要绑定到你的类然后当你创建一个新实例时你可以调用 myNewInstance.foo() 如果你导入你的类你可以调用一个静态方法