javascript:创建一个继承自多个构造函数原型的对象

the*_*osp 3 javascript inheritance constructor prototype

说我有两个构造函数:

A = function () {
    this.x = 'x';
};
A.prototype.a = 'a';

B = function () {
    this.y = 'y';
};
B.prototype.b = 'b';
Run Code Online (Sandbox Code Playgroud)

我怎样才能创建一个对象AB将从两者的原型继承?所以下面的例子将起作用:

ab.a === 'a'; // true
ab.b === 'b'; // true
A.prototype.a = 'm';
ab.a === 'm'; // true
B.prototype.b = 'n';
ab.b === 'n'; // true
Run Code Online (Sandbox Code Playgroud)

谢谢

T.J*_*der 7

你不能,只有一个原型链.你基本上有三个选择:

从一个继承,复制另一个

单个对象上具有属性方面所能做的就是从其中一个原型继承并复制另一个属性.显然这不是你想要的,因为你没有复制属性的实时参考方面,但是你可以在单个对象上拥有这些属性.

组成

另一种选择是组成:

var ab = {
    aness: new A(),
    bness: new B()
};

ab.aness.a === 'a'; // true
ab.bness.b === 'b'; // true
A.prototype.a = 'm';
ab.aness.a === 'm'; // true
B.prototype.b = 'n';
ab.bness.b === 'n'; // true
Run Code Online (Sandbox Code Playgroud)

所以现在,ab作为一个A方面(在它的aness属性中称之为"A-ness"),以及在其属性中的一个B方面(称之为"B-ness")bness.

通常当人们认为"我需要多重继承"时,组合是一个很好的选择(即使在允许多重继承的系统中).并非总是如此,但经常.

如果你需要为A-ness或B-ness添加函数ab,也可以访问另一个方面,你可以使用闭包来实现.例如,如果您将对象传递给期望查看A实例并调用其foo函数的第三方库,并且我们希望foo根据我们B方面的某些状态执行不同的操作,则可能会出现这种情况.例如:

function AB() {
    var aness, bness;

    this.aness = aness = new A();
    this.bness = bness = new B();

    // `foo` returns the `a` property of our composite if
    // it's been changed; otherwise, it returns the `b`
    // property of our composite.
    aness.foo = function() {
        // We want to use `A`'s normal `foo` unless our
        // B-ness `b` property is 42 for some reason.
        if (bness.b === 42) {
            // Our magic number, handle locally.
            return "The answer";
        }
        // Not our magic number, let `A` handle it
        return A.prototype.foo.call(this);
    };
}
var ab = new AB();
Run Code Online (Sandbox Code Playgroud)

但要注意上面的模式,因为它为构造函数生成的每个实例创建了一个新函数AB.如果有很多,它可能会成为一个内存问题.

在这一点上,我们开始偏向继承链和超级调用,我在这篇博文中更详细地讨论了这一点.

链接BA

如果你是Aand 的设计者B,那么继承可能是有意义的,然后你可以由构造函数创建:BAabB

A = function () {
    this.x = 'x';
};
A.prototype.a = 'a';

B = function () {
    this.y = 'y';
};
B.prototype = new A();
B.prototype.b = 'b';

ab = new B();

ab.a === 'a'; // true
ab.b === 'b'; // true
A.prototype.a = 'm';
ab.a === 'm'; // true
B.prototype.b = 'n';
ab.b === 'n'; // true
Run Code Online (Sandbox Code Playgroud)

...但这意味着所有 B对象也都是A对象,这可能不是您想要的.


偏离主题:我没有var在上面添加s,假设他们不在那里(例如,他们已经在代码中声明了你没有显示).

题外话2:除非你有一个很好的理由,我总是建议使用命名的函数,而不是匿名者(你分配的职能AB是匿名的).