2013-08-26 21 views
3

我一直在學習約翰Resig的JavaScript原型繼承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的原型屬性如何引用原型對象,請參考Person實例,都有swingSword屬性?

+1

你運行該代碼?是什麼讓你覺得'ninja1'既有'sayHello'也有'swingSword'? –

+0

當你做'Ninja.prototype = new Person();'時,Ninja的原型被完全覆蓋。而'ninja1'在這個結尾處不會有swingSword方法。這不是做原型繼承的方法。 – RoryKoehein

+0

對於不強制創建其父(新人)實例的繼承,您可以使用'Ninja.prototype = Object.create(Person.prototype);'或輔助函數。更多關於這裏的構造函數:http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711你沒有使用特定於實例的成員,但是如果你這樣做,你應該做'Person.call(this );'在忍者構造函數體中(見鏈接)。 – HMR

回答

4

[...],通過它的原型,有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 = ...之後,該swingSword附於原始prototype對象不再被引用。所以,創建新實例時不會使用它。


如果您打算設置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]] reference從創建它們時開始,無論可以對其構造函數的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/