2013-07-18 214 views
5

看起來好像我終於理解了JavaScript繼承以及它應該如何正確完成。這裏是我的代碼:JavaScript和原型繼承

function Human(eyes) { 
    this.eyes = eyes ? "Not blind" : "Blind"; 
} 
Human.prototype.canSee = function() { 
    return this.eyes; 
}; 
function Male(name, eyes) { 
    Human.call(this, eyes); 
    this.name = name; 
} 
Male.prototype = Object.create(Human.prototype); 
var Sethen = new Male("Sethen", true); 
console.log(Sethen.canSee()); //logs "Not blind" 

據我瞭解,使用Object.create創建繼承原型對象比使用new關鍵字好得多。這在我的腦海裏提出了一些問題。

  1. Male.prototype = Object.create(Human.prototype)原型鏈是Male.prototype --> Human.prototype --> Object.prototype --> null
  2. Male構造函數中,我使用Human.call(this, eyes);來調用一個超類,我不得不在Male構造函數中再次傳遞給Human構造函數。這看起來很痛苦,有沒有更簡單的方法來做到這一點?
  3. 爲什麼我有時會看到像Male.prototype = new Human();這樣的代碼......這似乎是不正確的。當我們這樣做時究竟發生了什麼?
+1

你見過這個http://stackoverflow.com/questions/13040684/javascript-inheritance-object-create-vs-new和這個http://stackoverflow.com/問題/ 4166616 /諒解 - 差異 - 對象 - 創建和新 - somefunction-in-j ??? – rafaelcastrocouto

+0

不,我沒有。我會看看。 – Sethen

回答

3

回答您的問題:

  1. 這是正確的。當您設置Male.prototype = Object.create(Human.prototype)時,您將原型鏈設置爲Male.prototype --> Human.prototype --> Object.prototype --> null。然後,當您創建var Sethen = new Male時,實例(Sethen)會從此原型鏈繼承。
  2. 不,您需要手動將參數傳遞給基礎構造函數。如果您想在Male函數本身內設置this.eyes = eyes ? "Not blind" : "Blind",但這只是代碼重複。你在做什麼是正確的。
  3. 這是舊的做事方式(在Object.create被標準化之前)。我會建議你不要使用它。對於大多數情況下,它與新方法相同。但是,使用此方法,您還會在Male.prototype上收到不需要的屬性,如eyes

當我們這樣做Male.prototype = new Human我們創建的Human一個新實例,並將其分配給Male.prototype。因此原型鏈是Male.prototype --> Human.prototype --> Object.prototype --> null。不過,我們也收到了我們不需要的財產Male.prototype.eyes。這應該只屬於Male的實例。

我會建議你閱讀我的博客文章。這是一個非常好的原型繼承引物:Aadit M Shah | Why Prototypal Inheritance Matters

+0

謝謝你!這爲我清理了一些事情。我認爲我們也得到了一些不需要的屬性,比如'eyes',但是不確定。 – Sethen

+0

使用Object.create輔助函數之前:http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711(仍然是如果你想支持IE 8)在這些幫助函數的構造函數可以在設置繼承之後將其設置爲正確的功能。如果你打算使用'constructor'屬性,你仍然需要這樣做。 – HMR

+1

@HMR啊。那麼,我現在使用的唯一幫助函數是['augment'](https://github.com/javascript/augment)。它使用'Object.create',但你也可以在不使用'Object.create'的情況下實現它。 –