Является ли это недостатком прототипной модели наследования JavaScript?

Я изучал прототипное наследование в JavaScript из " Секретов ниндзя" Джона Резига, и мне было интересно, что произойдет в следующем примере кода (который я только что придумал).

function Person() {}

Person.prototype.sayHello = function() {
    alert("Hello World");
}

function Ninja() {}

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

Ninja.prototype = new Person();

var ninja1 = new Ninja();

Насколько я знаю, результатом всех этих строк кода является то, что переменная ninja1 ссылки на Ninja объект, который через свой прототип имеет swingSword метод, и через прототипное наследование Personпрототип, имеет sayHello метод.

Где я запутался в следующем: так как собственность swingSword (который оказывается методом) был прикреплен к Ninjaпрототип, прежде чем личный экземпляр был назначен Ninjaпрототип swingSword свойство / метод будет перезаписано последующим присвоением Person пример? Если нет, то как NinjaСвойство prototype, которое ссылается на объект prototype, ссылается как на Person экземпляр, и есть swingSword имущество?

1 ответ

Решение

[...] что через свой прототип, имеет swingSword метод, [...]

В то время как остальная часть этого утверждения верна - это ninja1 Рекомендации Ninja (ну, технически, Ninja.prototype) и будет иметь sayHello через наследство - ваши последующие мысли верны относительно swingSword,

не будет swingSword свойство / метод будет перезаписано последующим присвоением Person пример?

В конце вашего фрагмента, ninja1.swingSword должно быть undefined,

console.log(typeof ninja1.swingSword); // 'undefined'

// as is:
console.log(typeof Ninja.prototype.swingSword); // 'undefined'

После Ninja.prototype = ..., оригинал prototype возражать, что swingSword был прикреплен к больше не ссылается. Таким образом, он не будет использоваться при создании новых экземпляров.


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

Ninja.prototype = new Person();

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

var ninja1 = new Ninja();

console.log(typeof ninja1.swingSword); // 'function'

И если ninja1 на самом деле есть swingSword, это, вероятно, означает, что он был создан до prototype был изменен.

Объекты сохраняют свои собственные [[Prototype]] ссылка с момента их создания независимо от того, какие изменения могут быть внесены в их конструктор prototype имущество.

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

var ninja1 = new Ninja();

Ninja.prototype = new Person(); // won't affect existing instances

var ninja2 = new Ninja();

console.log(typeof ninja1.swingSword); // function
console.log(typeof ninja2.swingSword); // undefined

Пример каждого: http://jsfiddle.net/G8uTk/

Другие вопросы по тегам