这两种继承有什么区别?

时间:2014-07-04 07:35:28

标签: javascript oop

说明两种类型的继承之间的区别?

function inherit(c,p){
    var F =function(){}
    F.prototype=p.prototype;
    c.prototype=new F();
}

AND

function inherit(c,p){
    c.prototype=p.prototype;
}

如果有的话,各自的利弊是什么?

1 个答案:

答案 0 :(得分:3)

在第二个中,cp最终都使用相同的对象作为其prototype属性。因此,向该对象添加内容会影响使用new cnew p创建的实例,因为这些实例从函数上的prototype属性获取其基础原型。这是一个问题,孩子不应该像那样影响父母的实例。

例如,使用第二个,我们遇到了这个问题:

function Parent() {
}
function Child() {
}
inherit(Child, Parent);
Parent.prototype.question = "Life, the Universe, and Everything";
Child.prototype.answer = 42;
var par = new Parent();
var ch = new Child();
console.log(par.question); // "Life, the Universe, and Everything"
console.log(ch.question);  // "Life, the Universe, and Everything"
console.log(par.answer);   // 42 <=== WRONG, Parent instances don't have the property
console.log(ch.answer);    // 42

上面的代码在内存中创建了这种情况(让我们使用一个名为__proto__的属性来表示一个对象的底层原型;这就是即将发布的ES6规范所做的事情):

                        The second one: Wrong
+-----------------+
| Function Parent |
+-----------------+          +---------------+
| prototype       |----+++-->| Object        |
+-----------------+    |||   +---------------+
                       |||   | question: ... |
+------------+         |||   | answer: 42    |
| Parent par |         |||   +---------------+ 
+------------+         |||
| __proto__  |---------+||
+------------+          ||
                        ||
+-----------------+     ||
| Function Child  |     ||
+-----------------+     ||
| prototype       |-----+|
+-----------------+      |
                         |
+-----------+            |
| Child ch  |            |
+-----------+            |
| __proto__ |------------+
+-----------+

使用第一个c.prototype是一个新的对象,其p.prototype作为其基础原型。将内容添加到c.prototype 赢得会影响使用new p创建的实例,只会影响使用new c创建的实例。但是,向p.prototype添加内容会影响两者,如果c意图从p继承,则有意义。

function Parent() {
}
function Child() {
}
inherit(Child, Parent);
Parent.prototype.question = "Life, the Universe, and Everything";
Child.prototype.answer = 42;
var par = new Parent();
var ch = new Child();
console.log(par.question); // "Life, the Universe, and Everything"
console.log(ch.question);  // "Life, the Universe, and Everything"
console.log(par.answer);   // undefined, Parent instances don't have the property
console.log(ch.answer);    // 42

这在内存中设置了这个:

                            The first one
+-----------------+
| Function Parent |
+-----------------+          +---------------+
| prototype       |----+---->| Object        |<-+
+-----------------+    |     +---------------+  |
                       |     | question: ... |  |
+------------+         |     +---------------+  |
| Parent par |         |                        |
+------------+         |                        |
| __proto__  |---------+                        |
+------------+                                  |
                                                |
+-----------------+                             |
| Function Child  |                             |
+-----------------+          +---------------+  |
| prototype       |------+-->| Object        |  |
+-----------------+      |   +---------------+  |
                         |   | __proto__     |--+
+-----------+            |   | answer: 42    |
| Child ch  |            |   +---------------+
+-----------+            |
| __proto__ |------------+
+-----------+
  

如果有的话,各自的利弊是什么?

第二个实际上是错误的。 : - )


附注:在启用ES5的环境中,第一个可以更简单:

function inherit(c,p){
    c.prototype = Object.create(p.prototype);
}

附注2:为了更加彻底,第一个应该是这样的:

function inherit(c,p){
    var F =function(){}
    F.prototype=p.prototype;
    c.prototype=new F();
    c.prototype.constructor = c;
}

或者这个:

function inherit(c,p){
    c.prototype = Object.create(p.prototype);
    c.prototype.constructor = c;
}

constructor对象的Function属性引用的对象的prototype属性应该指向该函数。这是在规范中设置函数的方式,尽管它实际上并没有使用 constructor属性。但是,有些人可能会使用它的代码,并希望规范的设置在那里。