JavaScript:Class.method 与 Class.prototype.method

IT技术 javascript oop prototype-programming
2021-02-08 06:44:04

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

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

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

5个回答

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

在 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();
@Menda 你的链接失效了
2021-03-13 06:44:04
@Raghavendra 不是
2021-03-23 06:44:04
但为什么 Function.prototype.method == Function.method ?
2021-04-09 06:44:04

是的,第一个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)来做这件事。这只是另一种方式,在我看来是不正确的方式。
2021-03-23 06:44:04
哦……这就是说的话,从字面上看,构造函数就是 JS 类在一天结束时真正的全部内容吗?其他所有东西要么堆积到构造函数中,要么完全是一个与类隔离的静态构造,除了名称/概念(就像一个隐含的“这个”明显可用)?(因此,我认为是集合的子集实际上不是子集。)
2021-03-28 06:44:04
@Andrew 也许超现实的感觉来自于此:在 JavaScript 中,类和构造函数是同一个东西顺便说一下,我一直回到这个图表这很奇怪,但奖励学习。最终它真的让我对 JavaScript 做类的方式或假装的方式感到困惑。理解构造函数属性的关键是 John Sonderson 的评论:b.constructor就像任何类属性解析为b.__proto__.constructor并因此指向Foo.
2021-04-03 06:44:04
@KarlMorrison Aminu 没有写“做事方式”,你只是自己写的,并对此表示反对。关于 ES6 与 ES2015,您的观点可能是公平的,但在对话中,人们通常会采用较短的约定来提高效率,因此我认为将其从写作中删除是不可能的,或者肯定是可取的。
2021-04-05 06:44:04
感谢您回答的 ES6 部分;这澄清了很多,尤其是与上面的 2 个“公共 + 特权”答案结合使用时。然而,我obj.constructor === Persontrue例子感到非常困惑...... Whaaaat?类实例的构造函数如何===成为类本身......?(这就像说集合的子集是集合本身,等等......)
2021-04-10 06:44:04

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

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

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

“另外,如果你改变了父对象的属性,如果子对象的相应属性没有改变,它就会被更新。” 不确定你的意思是什么。仅当您更改父对象的原型属性时才会这样吗?
2021-03-26 06:44:04

对于视觉学习者,在定义函数时没有 .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/

A. 静态方法:

      Class.method = function () { /* code */ }
  1. method()这是添加到另一个函数(此处为 Class)的函数属性
  2. 可以通过类/函数名称直接访问 method() Class.method();
  3. 无需创建任何对象/实例( new Class()) 来访问 method()。因此,您可以将其称为静态方法。

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

     Class.prototype.method = function () { /* code using this.values */ }
  1. method()这是添加到另一个函数原型(此处为 Class.prototype)的函数属性
  2. 可以 要么直接访问类名或一个对象/实例new Class())。
  3. 额外的好处-方法的这种方式()的定义将创建只有一个副本在记忆法()的,将被共享所有对象/实例的从已创建Class

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

   function Class () {
      this.method = function () { /* do something with the private members */};
   }
  1. method()这是在另一个函数(此处为 Class)中定义的方法
  2. 不能通过类/函数名称直接访问 method() Class.method();
  3. 需要new Class()为 method() 访问创建一个对象/实例 ( )。
  4. ()方法定义的这种方式将创建一个()的方法的独特副本每个对象使用构造函数创建(new Class())。
  5. 附加优势 - method() 范围的 Bcos 它拥有访问在构造函数(此处为 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
A.“不需要创建任何对象/实例(new Class())来访问method()。所以你可以把它作为一个静态方法来调用。” 是否可以从实例访问静态方法?如果是如何。消除这种歧义会很好。B.“您可以通过类名或对象/实例(new Class())直接访问。” 我认为添加一个通过类名(Class.prototype.method()) 访问的示例来澄清会有所帮助。起初我很困惑,因为我知道 Class.method() 不适用于原型方法。您的回答对我的理解很有帮助,非常感谢。
2021-03-19 06:44:04