简体   繁体   English

在javascript的类定义中添加原型

[英]adding prototype in class definition in javascript

reading the What techniques can be used to define a class in JavaScript, and what are their trade-offs? 阅读什么技术可以用来在JavaScript中定义类,以及它们的权衡是什么? on stackoverflow i understand that i can define a class via 在stackoverflow上,我知道我可以通过定义一个类

Method 1: 方法1:

function Person(name, gender){
   this.name = name;
   this.gender = gender;
}

and add functions in prototype so as to avoid member functions recreated every time its instantiated. 并在原型中添加函数,以避免每次实例化时重新创建成员函数。 like 喜欢

Person.prototype.speak = function(){
   alert("my name is" + this.name);
}

and create its instances via 并通过创建它的实例

var person = new Person("Bob", "M"); 

I think the creation of same object is possible with out new keyword like 我认为无需使用新关键字即可创建相同的对象

Method 2: 方法2:

var Person = function (name, gender) {

    return {name:name, gender:gender}; 

}

person  = Person("Bob", "M");

Is the second method doing exactly the same thing done by the first one? 第二种方法执行的功能与第一种方法完全相同吗? Also if so how would i mock up addition of functions via prototype (as we see in method 1's speak) in the second approach? 如果是这样的话 ,在第二种方法中,我将如何通过原型(如方法1所示)来模拟附加功能?

No, Method 2 != Method 1. The second method is creating a new anonymous object with a prototype that points at Object.prototype while the first is creating a new object with a prototype that points at Person.prototype . 否,方法2!=方法1的第二种方法是创建与在点a原型新的匿名对象Object.prototype ,而第一是创建与指向在一个原型的新对象Person.prototype

In psuedo-code: 在伪代码中:

// Method #1
function Person(name, gender) {
    // The magic JS does *for us* (but *only* when invoked with `new`)
    var this = {};
    // __proto__ is the *internal* prototype reference
    // It's not required to be accessible unless you're in an ES6 environment.
    this.__proto__ = Person.prototype;

    // Person.prototype is also created by JS for us
    // and provided with a reference (among other things)
    // to this function as prototype.constructor.

    // Our stuff
    this.name = name;
    this.gender = gender;

    // More JS magic
    return this;
}

// Method #2
function Person(name, gender) {
    // Just our stuff - no magic JS goodness here
    return {
        name: name, gender: gender
    };
}

As Sean Vieira explained the first method is not the same as the second method. 正如肖恩·维埃拉(Sean Vieira)解释的那样,第一种方法与第二种方法不同。 In the first method the instance inherits from Person.prototype . 在第一种方法中,实例继承自Person.prototype In the second method the instance inherits directly from Object.prototype . 在第二种方法中,实例直接从Object.prototype继承。

Method 1: 方法1:

        null
         ^
         |
         | __proto__
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
| Person.prototype |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
|      person      |
+------------------+

Method 2: 方法2:

        null
         ^
         |
         | __proto__
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
|      person      |
+------------------+

Interestingly the above diagrams show you that objects inherit from other objects in JavaScript, and not from constructors. 有趣的是,上面的图向您展示了对象是从 JavaScript中的其他对象继承的 ,而不是从构造函数继承的 Hence when you create new Person the instance inherits from Person.prototype , not from Person itself. 因此,当您创建new Person该实例是从Person.prototype继承的,而不是从Person本身继承的。

How is this relevant information? 这些相关信息如何? For starters it demonstrates that you don't need to create a constructor to creates instances of an object. 对于初学者,它表明您不需要创建构造函数来创建对象的实例。 Instead you directly create the prototype object as follows: 而是直接按如下方式创建原型对象:

var person = {
    create: function (name, gender) {
        var person = Object.create(this);
        person.gender = gender;
        person.name = name;
        return person;
    },
    speak: function () {
        alert("My name is " + this.name + ".");
    }
};

In the above example person is equivalent to Person.prototype . 在上面的示例中, person等同于Person.prototype You may now create an instance of person as follows: 您现在可以按以下方式创建person实例:

var bob = person.create("Bob", "M");

The prototype chain of bob will look like this: bob的原型链看起来像这样:

        null
         ^
         |
         | __proto__
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
|      person      |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
|       bob        |
+------------------+

So why should you create objects like this instead? 那么为什么要创建这样的对象呢?

  1. It looks cleaner. 看起来比较干净。 Everything is encapsulated in a single object literal. 一切都封装在单个对象文字中。
  2. It's easier to understand that objects inherit from objects. 更容易理解对象是从对象继承的。 No constructors needed. 不需要构造函数。
  3. You don't need to use new to create an instance. 您不需要使用new来创建实例。 This solves a lot of problems . 解决很多 问题

For more information about this pattern read my blog post on "Why Prototypal Inheritance Matters" . 有关此模式的更多信息,请阅读我的博客文章“为什么原型继承很重要”

Your examples are achieving the same thing with regards to accessing the properties, but they are not identical as the first method has the basic Object prototype. 您的示例在访问属性方面实现了相同的目的,但是它们并不相同,因为第一种方法具有基本的Object原型。 The answer to your second question is: 您的第二个问题的答案是:

function Person( name, gender ){
   return {
     name: name,
     gender: gender,
     speak: function(){
        alert("my name is" + this.name);
     }
   };
}

Here there is no prototype. 这里没有原型。 The function is baked into the object literal. 该函数被烘焙到对象文字中。 The only value in using a literal instead of a prototype would be to create a closure so you can have private variables eg: 使用文字而不是原型的唯一价值是创建一个闭包,因此您可以拥有私有变量,例如:

function Person( name, gender ){
   return {
     speak: function(){
        alert("my name is" + name);
     }
   };
}

Maybe this answer can explain a bit more about constructor functions, inheritance, private variables and overriding methods: Prototypical inheritance - writing up 也许这个答案可以解释更多有关构造函数,继承,私有变量和覆盖方法的信息: 原型继承-编写

The other answers already address your question; 其他答案已经解决了您的问题; creating an object as an object literal {prop:val,method:function(){}} and creating an object using constructor functions: var MyObject=function(){this.prop=val};MyObject.prototype.method=function(){} ; 将对象创建为对象文字{prop:val,method:function(){}}然后使用构造函数创建对象: var MyObject=function(){this.prop=val};MyObject.prototype.method=function(){} ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM