JavaScript: создайте объект, который наследует от прототипов более чем одного конструктора - PullRequest
3 голосов
/ 22 ноября 2010

Скажем, у меня есть два конструктора:

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

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

Как я могу создать объект 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

Спасибо

Ответы [ 2 ]

7 голосов
/ 22 ноября 2010

Вы не можете, есть только одна цепочка прототипов. У вас есть три варианта:

Наследовать от одного, копировать другого

Все, что вы можете сделать с точки зрения наличия свойств у одного объекта , наследуется от одного из прототипов и копирует свойства другого. Очевидно, что это не совсем то, что вам нужно, потому что у вас нет аспекта прямой ссылки на скопированные свойства, но это все, что вы можете сделать с точки зрения наличия этих свойств на одном объекте.

Состав

Другой вариант - композиция :

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 являются анонимными).

0 голосов
/ 22 ноября 2010

Ниже приведена ссылка, описывающая способ реализации множественного наследования в javascript:

http://www.polyglotinc.com/AJAXscratch/Class/InterfacesFromScratch.html

Это выглядит сложно.Как уже упоминалось, вероятно, лучше / безопаснее / проще найти другой путь.

...