你不能,只有一个原型链。你基本上有三个选择:
从一个继承,复制另一个
就单个对象上的属性而言,您所能做的就是从其中一个原型继承并复制另一个原型的属性。显然这不是您想要的,因为您没有复制属性的实时引用方面,但您可以在单个对象上拥有这些属性。
作曲
另一种选择是作曲:
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
所以现在,ab 在其aness 属性中作为A 方面(称之为“A-ness”),在其属性中作为B 方面(称之为“B-ness”) bness 财产。
通常当人们认为“我需要多重继承”时,组合是一个很好的选择(即使在允许多重继承的系统中也是如此)。请注意,并非总是如此,但经常如此。
如果您需要向 ab 的 A-ness 或 B-ness 添加还可以访问其他方面的函数,您可以使用闭包来实现。例如,如果您将一个对象传递给第三方库,该库希望看到一个 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();
但请注意上述模式,因为它会为AB 构造函数生成的每个实例 创建一个新函数。如果有很多,可能会成为内存问题。
在这一点上,我们开始误入继承链和超级调用,我在this blog post 中有更详细的讨论。
将B 链接到A
如果您是A 和B 的设计者,可能B 继承自A,然后您的ab 可以由B 构造函数:
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
...但这意味着 所有 B 对象也是 A 对象,这可能不是您想要的。
题外话:我没有在上面添加vars,因为假设它们不存在是有原因的(例如,它们已经在你的代码中声明了不显示)。
题外话2:除非你有充分的理由,否则我总是recommend using named functions 而不是匿名的(你分配给A 和B 的函数是匿名的)。