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

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

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


当前回答

对于视觉学习器,当定义没有.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+/切换注释部分

其他回答

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

在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();

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

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

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

A.静态方法:

      Class.method = function () { /* code */ }

method()在这里是一个函数属性添加到另一个函数(这里是Class)。 您可以通过类/函数名直接访问方法()。Class.method (); 不需要创建任何对象/实例(new Class())来访问方法()。你可以把它作为静态方法调用。

B.原型方法(所有实例共享):

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

method()在这里是一个函数属性添加到另一个函数原型(这里是Class.prototype)。 您可以直接通过类名或通过对象/实例(new class())访问。 增加的好处- method()定义的这种方式只会在内存中创建一个method()的副本,并且将在所有从类创建的对象/实例之间共享

C.类方法(每个实例都有自己的副本):

   function Class () {
      this.method = function () { /* do something with the private members */};
   }

method() here is a method defined inside an another function (here Class). You can't directly access the method() by the class / function name. Class.method(); You need to create an object/instance (new Class()) for the method() access. This way of method() definition will create a unique copy of the method() for each and every objects created using the constructor function (new Class()). Added advantage - Bcos of the method() scope it has the full right to access the local members(also called private members) declared inside the constructor function (here 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

对于视觉学习器,当定义没有.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+/切换注释部分

是的,第一个是静态方法,也称为类方法,而第二个是实例方法。

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

In 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 =新人员(“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 =新人(" aminu ", "Abubakar");

使用静态方法isPerson。

Person.isPerson (aminu);//返回true

使用实例方法sayHi。

aminu.sayHi ();//返回"Hi Aminu"

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