对象不继承原型函数

时间:2012-06-17 15:37:13

标签: javascript oop inheritance prototype

我有一个构造函数,它充当超类:

Bla = function(a){this.a = a;}

我将其原型化为包含一个简单的方法:

Bla.prototype.f = function(){console.log("f");

现在新Bla(1).f();将记录" f"在控制台中。但是,让我说我需要一个继承自Bla的子类:

Bla2 = function(a)
{
    this.base = Bla;
    this.base();
}

x = new Bla2(5);

现在,正如预期的那样,x.a给了我5。但是,x.fundefined!好像Bla2没有从Bla类继承它!为什么会发生这种情况,我该如何纠正呢?

1 个答案:

答案 0 :(得分:29)

  

似乎Bla2没有从Bla类继承它!

右。你没有做任何事情来连接那里的继承,你刚刚创建了一个名为Bla2的{​​{1}}成员,它是一个base实例。 Bla不是JavaScript中的特殊标识符。

在JavaScript中设置继承的典型方法如下:

base

...其中Object.create来自ES5,但这是其中一个很容易被大部分填充的东西。 (或者你可以使用一个只做最低限度而不试图完成所有// The base constructor function function Base(x) { // Base per-instance init this.x = x; } // An example Base function Base.prototype.foo = function() { console.log("I'm Base#foo, x = " + this.x); }; // The Derived constructor function function Derived(x, y) { // Normally you need to call `Base` as it may have per-instance // initialization it needs to do. You need to do it such that // within the call, `this` refers to the current `this`, so you // use `Function#call` or `Function#apply` as appropriate. Base.call(this, x); // Derived per-instance init this.y = y; } // Make the Derived.prototype be a new object backed up by the // Base.prototype. Derived.prototype = Object.create(Base.prototype); // Fix up the 'constructor' property Derived.prototype.constructor = Derived; // Add any Derived functions Derived.prototype.bar = function() { console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y); }; 的函数;见下文。)然后你使用它:

Object.create

Live example | source

在较旧的代码中,您有时会看到var d = new Derived(4, 2); d.foo(); // "I'm Base#foo, x = 4" d.bar(); // "I'm Derived#bar, x = 4, y = 2" 设置为这样:

Derived.prototype

...但是这样做是有问题的:Derived.prototype = new Base(); 可以进行每个实例初始化,这不适合整个Base继承。它甚至可能需要参数(正如我们的Derived所做的那样;我们将为Base传递什么?)。相反,让x成为Derived.prototype支持的新对象,我们得到了正确的东西。然后我们从Base.prototype内调用Base来获取每个实例的初始化。

以上是非常基本的,您可以看到涉及许多步骤。它也很少或根本没有使“超级调用”变得容易和高度可维护。这就是为什么你会看到如此多的“继承”脚本,比如Prototype的Derived,Dean Edwards的Base2,或者(咳嗽)我自己的Lineage


如果您不能依赖环境中的ES5功能,并且不希望包含支持Class基础知识的垫片,则可以在其位置使用此功能:

Object.create

然后代替

function simpleCreate(proto) {
    function Ctor() {
    }
    ctor.prototype = proto;
    return new Ctor();
}
你会这样做:

Derived.prototype = Object.create(Base.prototype);

当然,你可以做更多的事情来自动挂钩 - 这Derived.prototype = simpleCreate(Base.prototype); 基本上都是这样。


......最后:上面我为了简单起见使用了匿名函数,例如:

Lineage

...但我不会在我的真实代码中这样做,因为I like to help my tools help me。因此,我倾向于在每个“类”(构造函数和相关原型)周围使用模块模式,并使用函数声明(因为我为Web工作,IE7和IE8 still have problems与命名函数表达式。所以,如果我没有使用Base.prototype.foo = function() { // ... }; ,我会按照以下方式执行上述操作:

Lineage

......或类似的东西。 Live copy | source