Конструкторы и наследование в JavaScript

Речь идет о «наследовании» в JavaScript.

Предположим, я создаю конструктор Bird() и еще один конструктор с именем Parrot(), который я делаю для «наследования» свойств Bird, назначая его экземпляр прототипу Parrot, как показано в следующем коде:

function Bird() {
    this.fly = function(){};
}

function Parrot() {
    this.talk = function(){ alert("praa!!"); };
}
Parrot.prototype = new Bird();

var p = new Parrot();

p.talk(); // Alerts "praa!!"
alert(p.constructor); // Alerts the Bird function!?!?!

После того, как я создал экземпляр Parrot, почему его свойство .constructor является Bird(), а не Parrot(), который является конструктором, который я использовал для создания объекта?


person nandilugio    schedule 19.03.2010    source источник
comment
Протестировано в современных Firefox, Chrome, IExplorer и Safari с тем же результатом... :p   -  person nandilugio    schedule 19.03.2010


Ответы (2)


Прототип — это объект, как и все остальное в JavaScript, а присваивание объектов осуществляется по ссылке. Вы только что назначили новую птицу прототипу попугая, поэтому прототип попугая теперь является экземпляром птицы. А конструктором птицы является Птица.

Вы можете исправить это с помощью строки

Parrot.prototype.constructor = Parrot;

Другой способ сделать это — назначить клон прототипа Bird для Parrot.prototype.

function deepClone(obj) {
    var clone = {};
    for(var i in obj) {
        if(typeof(obj[i])==="object") {
            clone[i] = deepClone(obj[i]);
        } else {
            clone[i] = obj[i];
        }
    }
    return clone;
}


Parrot.prototype = deepClone(Bird.prototype);
Parrot.prototype.constructor = Parrot;

Я предпочитаю это, потому что:

1) он сохраняет создание произвольного экземпляра птицы (что, если что-то считает, сколько птиц было создано)

2) Что, если конструктор Bird принимает аргумент, проверенный в теле конструктора? Затем вызов:

Parrot.prototype = new Bird();

затем может вызвать нулевой указатель

person plodder    schedule 19.03.2010
comment
Ах! Наконец-то я понял: p Parrot.prototype, экземпляр Bird с уже определенным .constructor (равным Bird), используется в Parrot для создания нового экземпляра. Что мне кажется странным, так это то, что .constructor не переопределяется автоматически. В любом случае, знание этого облегчает решение (как вы предложили). Большое спасибо! - person nandilugio; 21.03.2010

Конструктор относится к функции, которая создает прототип экземпляра (а не сам экземпляр).

person machine elf    schedule 19.03.2010