Вы не можете, есть только одна цепочка прототипов. У вас есть три варианта:
Наследовать от одного, копировать другого
Все, что вы можете сделать с точки зрения наличия свойств у одного объекта , наследуется от одного из прототипов и копирует свойства другого. Очевидно, что это не совсем то, что вам нужно, потому что у вас нет аспекта прямой ссылки на скопированные свойства, но это все, что вы можете сделать с точки зрения наличия этих свойств на одном объекте.
Состав
Другой вариант - композиция :
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
как аспект A
(назовите его "A-ness") в его свойстве aness
, и аспект 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();
Однако остерегайтесь приведенного выше шаблона, поскольку он создает новую функцию для каждого экземпляра , сгенерированного конструктором AB
. Если их много, это может стать проблемой с памятью.
На этом этапе мы начинаем переходить к цепочкам наследования и супер-вызовам, о которых я расскажу более подробно в этом сообщении в блоге .
Ссылка 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
объектами, что может быть не тем, что вы хотите.
Не по теме : я не добавил var
s к вышесказанному при условии, что есть причина, по которой их нет (например, они уже объявлены в коде, который вы не показывая).
Не по теме 2 : Если у вас нет веских причин, я всегда рекомендую использовать именованных функций вместо анонимных (назначаемых вами функций) A
и B
являются анонимными).