JavaScript:Class.method与Class.prototype.method


498

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

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

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

Answers:


696

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

在JavaScript函数中,一类对象是一流的,这意味着您可以像对待任何对象一样对待它们,在这种情况下,您只需向函数object添加一个属性。

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

1
但是为什么是Function.prototype.method == Function.method?
Raghavendra 2015年

1
@Raghavendra不是
Zorgatone

1
@Menda,您的链接已死
Eugen Sunic

19

当创建多个MyClass实例时,内存中仍然仍然只有一个publicMethod实例,但是如果使用privateMethod,则最终将创建许多实例,而staticMethod与对象实例没有任何关系。

这就是为什么原型可以节省内存。

另外,如果您更改父对象的属性,并且子对象的相应属性没有更改,则会对其进行更新。


15

对于视觉学习者,在定义函数时不使用 .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& 单击上面的jsbin链接生成的结果以逐步执行代码。 用+ 切换评论的部分JS Bin

ctrl/


15

是的,第一个是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;
}

在以上代码中,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}`;
   }
}

看看如何使用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主要是在现有的基于原型的继承模型是语法糖。


在“ ES6”中,您仅描述语法糖。这不是“ ES2015”的方式(请停止使用ES6的每个人都使用术语ES2015)。这只是另一种方式,我认为这是不正确的方式。
莫里森

2
@KarlMorrison Aminu没有写“这样做的方式”,您只是自己写了这个,并对此表示反对。关于ES6与ES2015,您的观点可能是公平的,但是在交谈中人们通常会采用简短的约定以提高效率,因此我认为将其从写作中删除是不可能的,或者肯定是明智的。
wuliwong

感谢您回答的ES6部分;这说明了很多问题,尤其是与上述2个“公共+特权”答案结合使用时。但是,我被您的榜样彻底弄糊涂了。。。类实例的构造函数如何类本身...?(这就像说集合的子集就是集合本身,等等。)obj.constructor === Persontrue===
Andrew

呵呵...这就是这么说的意思,实际上,构造函数就是JS类在一天结束时真正存在的全部吗?除了名称/概念之外,其他所有东西都堆积在构造函数中,还是完全与类隔离的静态构造(就像隐含的“ this”明显可用)一样?(因此,我认为实际上是集合的一个子集,实际上不是一个子集。)
Andrew
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.