JavaScript:Class.method vs. Class.prototype.method

pos*_*nal 481 javascript oop prototype-programming

以下两个声明之间有什么区别?

Class.method = function () { /* code */ }
Class.prototype.method = function () { /* code using this.values */ }
Run Code Online (Sandbox Code Playgroud)

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

CMS*_*CMS 684

是的,第一个函数与该构造函数的对象实例没有关系,您可以将其视为"静态方法".

在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();
Run Code Online (Sandbox Code Playgroud)

  • 这取自:http://code.google.com/intl/es/speed/articles/optimizing-javascript.html同样重要的是,如果我们要创建许多`MyClass`实例,我们正在为每个实例创建实例一个函数`privilegedMethod`.但是`publicMethod`只为所有创建的实例构造一次. (60认同)

小智 17

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

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

此外,如果更改父对象的属性,子项的相应属性是否未更改,则会更新它.


SAm*_*SAm 13

对于视觉学习者,在没有定义功能时 .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`  
Run Code Online (Sandbox Code Playgroud)

使用相同的代码,如果.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`
Run Code Online (Sandbox Code Playgroud)

为了更清楚,

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
Run Code Online (Sandbox Code Playgroud)

****请注意,对于上面的示例,someInstance.method()将不会执行,因为
ExampleClass.method()导致错误并且执行无法继续.
但为了说明和易于理解,我保留了这个序列.****

chrome developer console& 上面的jsbin链接生成的结果来逐步执行代码. 使用+ 切换注释部分JS Bin

ctrl/


Ami*_*ano 9

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

请考虑以下示例,以更详细地了解它.

在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;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,isPerson是一个静态方法,sayHi而是一个实例方法Person.

下面是如何从Person构造函数创建对象.

var aminu = new Person("Aminu", "Abubakar");

使用静态方法isPerson.

Person.isPerson(aminu); // will return true

使用实例方法sayHi.

aminu.sayHi(); // will return "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}`;
   }
}
Run Code Online (Sandbox Code Playgroud)

查看static关键字如何用于声明静态方法isPerson.

创建Person类的对象.

const aminu = new Person("Aminu", "Abubakar");

使用静态方法isPerson.

Person.isPerson(aminu); // will return true

使用实例方法sayHi.

aminu.sayHi(); // will return "Hi Aminu"

注意:两个示例基本相同,JavaScript仍然是无类语言.在class中介绍ES6主要是在现有的基于原型的继承模型是语法糖.

  • @KarlMorrison Aminu 没有写“这样做的方法”,你只是自己写的,并对它表示反对。你关于 ES6 与 ES2015 的观点可能是公平的,但在对话中,人们经常采用更短的约定来提高效率,所以我认为从写作中删除它是不可能的,或者肯定是可取的。 (2认同)