我们可以称之为真正的原型继承吗?

时间:2011-05-04 08:42:33

标签: javascript inheritance prototypal-inheritance

我总是对人们试图强迫某种形式的经典继承成为javascript的方式感到惊讶。我设计了一个方法来继承某些对象b来自对象a的原型方法,而不是从对象b添加原型方法到对象a,使用来自 1 。现在我很好奇:你会说这真的是原型'继承'吗?这是一种可行的方法吗?它有pittfals吗?

以下是一些示例代码:

Object.prototype.inheritsFrom = function(obj){
    var prototo   = this.prototype, 
        protofrom = obj.prototype;
    for (var l in protofrom) {
        if (protofrom.hasOwnProperty(l)){
            prototo[l] = protofrom[l];
        }
    }
}

function Obj1(){
    var const1 = 25;
    if (!Obj1.prototype.getConst1){
       Obj1.prototype.getConst1 = function(){
           return const1;
       }
    }
}

function Obj2(){
    var const2 = 50;
    if (!Obj2.prototype.getConst2){
       Obj2.prototype.getConst2 = function(){
           return const2;
       }
    }
    Obj2.inheritsFrom(Obj1);
}

var instanceA = new Obj1,
    instanceB = new Obj2;

现在instanceA包含方法getConst1instanceB包含方法getConst1getConst2,您可以在this jsfiddle中看到。

1 通过在构造函数中分配原型方法,有效地使用由此创建的闭包。

1 个答案:

答案 0 :(得分:3)

不,那不是典型的继承。在真正的原型继承中,对原型的更改出现在依赖于该原型的对象中。在你的例子中,他们没有,因为他们只是被复制。

我并不是说在某些情况下它可能不是另一种有用的继承形式,但它不是典型的。从某种意义上说,我甚至不确定它的继承性,虽然我认为无论哪种方式都可以论证,无论如何都无关紧要。

以下是添加原型的示例:

function Parent() {
}
Parent.prototype.foo = function() {
  display("foo!");
};

function Child() {
}
Child.prototype = new Parent();

var c = new Child();

display("[before] typeof c.foo === '" + typeof c.foo + "'");
// shows "[before] typeof c.foo === 'function'"
display("[before] typeof c.bar === '" + typeof c.bar + "'");
// shows "[before] typeof c.bar === 'undefined'"
display("Note that c.bar is currently undefined");

Parent.prototype.bar = function() {
  display("bar!");
};

display("[after] typeof c.bar === '" + typeof c.bar + "'");
// shows "[after] typeof c.bar === 'function'"
display("Now c.bar is a function");

c.foo();
c.bar();

Live copy

请注意,这不是一个模糊的案例。毕竟,您自己的代码依赖于Object.prototype的更改,这些更改反映在已经已从派生的其他内容中Function


偏离主题强烈建议不要向Object.prototype添加任何内容。它将破坏大量代码,假设在for..in上使用{}将不会产生任何属性。直到你能够可靠地将添加标记为不可枚举(ECMAScript5现在提供了一种方法来实现这一点,但大多数实现还没有),只需远离Object.prototype。只是一个推荐。此外,在您的情况下,它没有意义,因为inheritsFrom仅适用于Function个实例,因此您需要将其添加到Function.prototype(这很多)不太危险)。