以下两个声明之间有什么区别?
Class.method = function () { /* code */ }
Class.prototype.method = function () { /* code using this.values */ }
把第一条语句看作静态方法的声明,第二条语句看作实例方法的声明,这样理解是否合适?
以下两个声明之间有什么区别?
Class.method = function () { /* code */ }
Class.prototype.method = function () { /* code using this.values */ }
把第一条语句看作静态方法的声明,第二条语句看作实例方法的声明,这样理解是否合适?
是的,第一个函数与构造函数的对象实例没有关系,你可以将其视为'静态方法'。
在JavaScript中,函数是一等公民对象,这意味着您可以像处理任何对象一样处理它们,在这种情况下,您只是向函数对象添加属性。
第二个函数,由于您正在扩展构造函数原型,它将对使用new
关键字创建的所有对象实例可用,并且该函数内部的上下文(this
关键字)将引用您调用它的实际对象实例。
考虑以下示例:
// constructor function
function MyClass () {
var privateVariable; // private member only available within the constructor fn
this.privilegedMethod = function () { // it can access private members
//..
};
}
// A 'static method', it's just like a normal function
// it has no relation with any 'MyClass' object instance
MyClass.staticMethod = function () {};
MyClass.prototype.publicMethod = function () {
// the 'this' keyword refers to the object instance
// you can access only 'privileged' and 'public' members
};
var myObj = new MyClass(); // new object instance
myObj.publicMethod();
MyClass.staticMethod();
是的,第一个是被称为静态方法
或类方法
的方法,而第二个是实例方法
。
考虑以下示例,以更详细地了解它。
在ES5中
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.isPerson = function(obj) {
return obj.constructor === Person;
}
Person.prototype.sayHi = function() {
return "Hi " + this.firstName;
}
在上述代码中,isPerson
是一个静态方法,而sayHi
是Person
的实例方法。
以下是如何从Person
构造函数创建对象。
var aminu = new Person("Aminu", "Abubakar");
使用静态方法isPerson
。
Person.isPerson(aminu); //将返回true
使用实例方法sayHi
。
aminu.sayHi(); //将返回"Hi Aminu"
在ES6中class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
static isPerson(obj) {
return obj.constructor === Person;
}
sayHi() {
return `Hi ${this.firstName}`;
}
}
观察如何使用static
关键字声明静态方法isPerson
。
创建一个Person
类对象。
const aminu = new Person("Aminu", "Abubakar");
使用静态方法isPerson
。
Person.isPerson(aminu); // 将返回true
使用实例方法sayHi
。
aminu.sayHi(); // 将返回"Hi Aminu"
注意:这两个示例本质上是相同的,JavaScript仍然是一种无类别的语言。在ES6中引入的class
主要是现有基于原型的继承模型的一种语法糖。
obj.constructor === Person
为true
的例子感到非常困惑...什么?一个类实例的构造函数怎么可能等于类本身呢...?(这就像说一个集合的子集是集合本身等等...) - Andrewb.constructor
像任何类属性一样解析为 b.__proto__.constructor
,从而指向 Foo
。 - Bob Stein对于视觉学习者来说,在不使用 .prototype
的情况下定义函数
ExampleClass = function(){};
ExampleClass.method = function(customString){
console.log((customString !== undefined)?
customString :
"called from func def.");}
ExampleClass.method(); // >> output: `called from func def.`
var someInstance = new ExampleClass();
someInstance.method('Called from instance');
// >> error! `someInstance.method is not a function`
使用相同的代码,如果添加了.prototype
,
ExampleClass.prototype.method = function(customString){
console.log((customString !== undefined)?
customString :
"called from func def.");}
ExampleClass.method();
// > error! `ExampleClass.method is not a function.`
var someInstance = new ExampleClass();
someInstance.method('Called from instance');
// > output: `Called from instance`
为了更清晰明了,ExampleClass = function(){};
ExampleClass.directM = function(){} //M for method
ExampleClass.prototype.protoM = function(){}
var instanceOfExample = new ExampleClass();
ExampleClass.directM(); ✓ works
instanceOfExample.directM(); x Error!
ExampleClass.protoM(); x Error!
instanceOfExample.protoM(); ✓ works
请注意,上面的示例中,一些实例方法someInstance.method()将不会被执行,因为ExampleClass.method()会导致错误并且无法继续执行。
但是为了说明和便于理解,我保留了这个顺序。
从Chrome开发者控制台
和JS Bin
生成结果。
单击上面的jsbin链接以逐步执行代码。
使用ctrl+/切换注释部分。
A. 静态方法:
Class.method = function () { /* code */ }
method()
是一个函数属性,添加到了另一个函数(这里是类Class)中。Class.method();
new Class()
)来访问方法(method())。因此,你可以将其称为静态方法。B. 原型方法(在所有实例之间共享):
Class.prototype.method = function () { /* code using this.values */ }
method()
在这里是一个函数属性,添加到另一个函数原型中(这里是 Class.prototype)。new Class()
)直接访问它。Class
创建的所有对象/实例之间共享。C. 类方法(每个实例都有自己的副本):
function Class () {
this.method = function () { /* do something with the private members */};
}
method()
是在另一个函数(这里是类)内部定义的方法。Class.method();
new Class()
)来访问 method()。new Class()
)创建的每个对象创建一个唯一副本的方法()。示例:
function Class() {
var str = "Constructor method"; // private variable
this.method = function () { console.log(str); };
}
Class.prototype.method = function() { console.log("Prototype method"); };
Class.method = function() { console.log("Static method"); };
new Class().method(); // Constructor method
// Bcos Constructor method() has more priority over the Prototype method()
// Bcos of the existence of the Constructor method(), the Prototype method
// will not be looked up. But you call it by explicity, if you want.
// Using instance
new Class().constructor.prototype.method(); // Prototype method
// Using class name
Class.prototype.method(); // Prototype method
// Access the static method by class name
Class.method(); // Static method