在javascript中的类定义中添加原型

时间:2013-07-02 18:18:14

标签: javascript class object prototype

在stackoverflow上读取What techniques can be used to define a class in JavaScript, and what are their trade-offs?我知道我可以通过

定义一个类

方法1:

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

并在原型中添加函数,以避免每次实例化时重新创建成员函数。像

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

并通过

创建其实例
var person = new Person("Bob", "M"); 

我认为使用新的关键字

可以创建相同的对象

方法2:

var Person = function (name, gender) {

    return {name:name, gender:gender}; 

}

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

第二种方法是否完成了第一种完全相同的操作?如果是这样的话,我将如何在第二种方法中通过原型模拟添加函数(正如我们在方法1中所说的那样)

4 个答案:

答案 0 :(得分:5)

否,方法2!=方法1.第二种方法是创建一个新的匿名对象,其原型指向Object.prototype,而第一种方法创建一个新对象,其原型指向{{1} }。

在伪代码中:

Person.prototype

答案 1 :(得分:3)

正如Sean Vieira所解释的那样,第一种方法与第二种方法不同。在第一种方法中,实例继承自Person.prototype。在第二种方法中,实例直接从Object.prototype继承。

方法1:

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

方法2:

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

有趣的是,上面的图表显示了对象继承自JavaScript中的其他对象,而不是来自构造函数。因此,当您创建new Person时,实例将继承自Person.prototype,而非来自Person本身。

这些相关信息如何?对于初学者来说,它表明您不需要创建构造函数来创建对象的实例。而是直接创建原型对象,如下所示:

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 + ".");
    }
};

在上面的示例中,person相当于Person.prototype。您现在可以创建person的实例,如下所示:

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

bob的原型链将如下所示:

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

那么为什么要创建这样的对象呢?

  1. 看起来更干净。所有内容都封装在一个对象文字中。
  2. 更容易理解对象是从对象继承的。不需要构造函数。
  3. 您不需要使用new来创建实例。这solves lot problems。{/ li>

    有关此模式的详细信息,请阅读"Why Prototypal Inheritance Matters"上的博文。

答案 2 :(得分:0)

您的示例在访问属性方面实现了相同的目标,但它们并不相同,因为第一种方法具有基本的Object原型。你的第二个问题的答案是:

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

这里没有原型。该函数被烘焙到对象文字中。使用文字而不是原型的唯一价值是创建一个闭包,这样你就可以拥有私有变量,例如:

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

答案 3 :(得分:0)

也许这个答案可以解释一下构造函数,继承,私有变量和重写方法:Prototypical inheritance - writing up

其他答案已经解决了你的问题;将对象创建为对象文字{prop:val,method:function(){}}并使用构造函数创建对象:var MyObject=function(){this.prop=val};MyObject.prototype.method=function(){};