2012-09-12 50 views
0

爲什麼這...繼承與CoffeeScript的

class Person 
    name: "initial name" 

    constructor: (@name) -> 


class User extends Person 
    password: "initial password" 


f = new User "Felds" 

console.log f 
console.log "my name is '#{f.name}' and my password is '#{f.password}'" 

b = new User "Bob" 
b.password = "bob's password" 

console.log b 

...當通過coffee -p test.coffee | node輸出這個運行?

{ name: 'Felds' } 
my name is 'Felds' and my password is 'initial password' 
{ name: 'Bob', password: 'bob\'s password' } 

爲什麼不上console.log fpassword物業展?它在哪裏存儲,它是如何檢索的?

+1

你可以直接寫'coffee test.coffee'你不需要做這個瘋狂的事。 – david

+0

@david我試圖理解生成的代碼(因此'-p'),然後有時我堅持'|節點「的前面,以運行代碼。無論如何,謝謝你的提示。 ;) –

回答

3

'initial password'值存儲在Person.prototype.password中。 Person.prototype是具有在Person實例之間共享的所有常見屬性的對象。當您訪問aPersonInstance.password時,首先在aPersonInstance對象中查找密碼屬性;如果沒有找到它,它將在其原型中查找,然後在其原型的原型中查找,等等。

console.log f不會顯示f的原型的屬性,只存儲在f自身的屬性(也稱爲f自己屬性)。當你與b.password = 'bob\'s password'分配Bob的密碼你在b本身創建一個新的password屬性,現在將要訪問b.password的價值,即使b的原型仍具有'initial password'值。我希望這是有道理的= P

通過將'initial password'存儲在原型中,您將在所有Person實例之間共享該值作爲一種默認值。這對於字符串或其他基元(不可變)類型來說是完美的。但是如果要使用數組或其他可變對象來處理,則必須格外小心,因爲同一對象將在所有類的實例之間共享,並且如果其中一個對象修改了它,例如, @someArray.push 5,所有其他人都會看到它。在這些情況下,通常最好在類構造函數中初始化屬性,如@someArray = [],以保證每個實例具有不同的數組/對象屬性。

+0

很好的答案。我刪除了我的,所以你可能想編輯最後一段。 –

+0

感謝您的錯字修復,馬克安德烈。我已經編輯了最後一段,試圖提到你在答案中提出的建議,因爲我認爲在原型中使用可變對象的困惑,然後得到意想不到的結果是相當複雜的= D – epidemian

0

我想給ü簡單&快速的答案,但不完全正確的Javascript:

變量password您在class User定義爲User.prototype.password,變量就像類變量在面向對象的語言。 它不是f的實例變量,所以當你console.log f,你不能看到password

但如果你檢索f.password,那麼你仍然會得到值'initial password'。當一個實例本身無法找到變量時,它將繼續在其類中找到它,即User

b.passwordb中的一個實例變量,所以console可以註銷它。