JavaScript:类。method vs. Class.prototype.method

下面两个声明有什么不同?

Class.method = function () { /* code */ }
Class.prototype.method = function () { /* code using this.values */ }

是否可以将第一个语句视为静态方法的声明,而第二个语句视为实例方法的声明?

204460 次浏览

是的,第一个函数与构造函数的对象实例没有关系,你可以把它看作的静态方法

在JavaScript中,函数是一流< em > < / em >对象,这意味着你可以像对待任何对象一样对待它们,在这种情况下,你只需要向函数对象添加一个属性。

第二个函数,当您扩展构造函数原型时,它将对使用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();

当您创建多个MyClass实例时,内存中仍然只有一个publicMethod实例,但在privilegedMethod的情况下,您将最终创建大量实例,而staticMethod与对象实例没有关系。

这就是原型节省内存的原因。

同样,如果你改变了父对象的属性,如果子对象对应的属性没有被改变,它就会被更新。

对于视觉学习者,当定义没有.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 developer console &# EYZ2 < br > 单击上面的jsbin链接来逐步执行代码 用ctrl+/

切换评论部分

是的,第一个是static method,也叫class method,而第二个是instance method

考虑下面的例子,以更详细地理解它。

# EYZ0

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是一个静态方法,而sayHiPerson的实例方法。

下面是如何从Person构造函数创建一个对象。

# EYZ0

使用静态方法isPerson

# EYZ0

使用实例方法sayHi

# EYZ0

在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类的对象。

# EYZ0

使用静态方法isPerson

# EYZ0

使用实例方法sayHi

# EYZ0

这两个例子本质上是一样的,JavaScript仍然是一种无类语言。ES6中引入的class主要是对现有的基于原型的继承模型的语法补充。

< >强。静态方法:< / >强

      Class.method = function () { /* code */ }
  1. method()这里是一个函数财产添加到另一个函数(这里是类)。
  2. 通过类/函数的名字直接访问方法()。# EYZ0
  3. 没有需要创建任何对象/实例 (new Class())来访问方法()。你可以叫它静态方法。

<强> B。原型方法(在所有实例间共享):

     Class.prototype.method = function () { /* code using this.values */ }
  1. 这里是一个函数财产添加到另一个函数原型(这里是Class.prototype)。
  2. 可以 要么直接通过类名对象/实例 (new Class())访问。
  3. 增加的好处-这种方法()定义将在内存中创建方法()的只有一份,并将从Class创建的所有对象的实例的之间创建共享

<强> C。类方法(每个实例都有自己的副本):

   function Class () {
this.method = function () { /* do something with the private members */};
}
  1. 这里的method()是在另一个函数(这里的类)中定义的方法。
  2. 通过类/函数的名字直接访问方法()。# EYZ0
  3. 需要为方法()访问创建一个对象/实例(new Class())。
  4. 这种方法()定义将为使用构造函数(new Class())创建的每一个物体创建一个方法的唯一副本()
  5. 增加的优势-由于方法()的作用域,它有完全的权利访问在构造函数(这里是类)中声明的当地的成员(也称为私人成员)

例子:

    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