Вы хотите это вместо:
function Man(name) {
Human.call(this, name, "Male");
}
Что этот код делает
Похоже, вы пытаетесь вызвать только конструктор родителя, Human
, что не является наследованием прототипа. Приведенный выше код принимает конструктор для Human
и применяет его к this
- новому объекту Man
.
Что делает ваш код
Линия Man.prototype = new Human(name, "Male")
меняет прототип Man
каждый раз, когда создается новый Человек . Мало того, вы завершаете переназначение объекта-прототипа, и поэтому он будет применяться только к объектам, созданным после этого назначения - то есть не к первому. Следовательно, m.name
не определено.
Правильное наследование прототипа
Обратите внимание, что вызов конструктора родителя, как в моем коде выше, не заставит Man
автоматически наследовать любые методы, назначенные Human.prototype
. Лучший способ сделать это - клонировать Human.prototype
в Man.prototype
, но вне каких-либо конструкторов. Как это:
function Man(name) {
Human.call(this, name, "Male");
}
function inherit(parent, child) {
if (Object.create) child.prototype = Object.create(parent.prototype);
else {
for (var key in parent.prototype) {
if (!parent.prototype.hasOwnProperty(key)) continue;
child.prototype[key] = parent.prototype[key];
}
}
}
inherit(Human, Man);
Это может показаться довольно многословным, и альтернатива может заключаться в следующем:
Man.prototype = new Human('no name', 'Male');
Который будет работать , но вызывает нежелательные побочные эффекты, так как мы вынуждены присвоить тупое имя для prototype
, и это позволяет конструктору для Human
вызывать дополнительное время только для Назначение прототипа. Будьте осторожны, если вы пойдете по этому пути и позже измените конструктор Human
, чтобы он делал больше, чем просто присваивал свойства this
.