原型鏈繼承基本想法就是讓一個原型物件指向另一個類型的實例
function SuperType() { this.property = true } SuperType.prototype.getSuperValue = function () { return this.property } function SubType() { this.subproperty = false } SubType.prototype = new SuperType() SubType.prototype.getSubValue = function () { return this.subproperty } var instance = new SubType() console.log(instance.getSuperValue()) // true
程式碼定義了兩個類型SuperType和SubType,每個類型分別有一個屬性和一個方法,SubType繼承了SuperType,而繼承是透過建立SuperType的實例,並將該實例賦給SubType.prototype來實現的。
實作的本質是重寫原型物件,代之以新類型的實例,那麼存在SuperType的實例中的所有屬性和方法,現在也存在於SubType.prototype中了。
我們知道,在建立一個實例的時候,實例物件中會有一個內部指標指向創建它的原型,進行關聯起來,在這裡程式碼SubType.prototype = new SuperType(),也會在SubType .prototype建立一個內部指針,將SubType.prototype與SuperType關聯起來。
所以instance指向SubType的原型,SubType的原型又指向SuperType的原型,繼而在instance在呼叫getSuperValue()方法的時候,會順著這條鏈一直往上找。
新增方法
在為SubType原型新增方法的時候,如果,父類別上也有同樣的名字,SubType將會覆寫這個方法,達到重新的目的。 但是這個方法依然存在於父類別中。
記住不能以字面量的形式添加,因為,上面說過透過實例繼承本質上就是重寫,再使用字面量形式,又是一次重寫了,但這次重寫沒有跟父類別有任何關聯,所以就會導致原型鏈截斷。
function SuperType() { this.property = true } SuperType.prototype.getSuperValue = function () { return this.property } function SubType() { this.subproperty = false } SubType.prototype = new SuperType() SubType.prototype = { getSubValue:function () { return this.subproperty } } var instance = new SubType() console.log(instance.getSuperValue()) // error
問題
單純的使用原型鏈繼承,主要問題來自包含引用類型值的原型。
function SuperType() { this.colors = ['red', 'blue', 'green'] } function SubType() { } SubType.prototype = new SuperType() var instance1 = new SubType() var instance2 = new SubType() instance1.colors.push('black') console.log(instance1.colors) // ["red", "blue", "green", "black"] console.log(instance2.colors) // ["red", "blue", "green", "black"]
在SuperType建構子定義了一個colors屬性,當SubType透過原型鏈繼承後,這個屬性就會出現SubType.prototype中,就跟專門創建了SubType.prototype.colors一樣,所以會導致SubType的所有實例都會共用這個屬性,所以instance1修改colors這個參考型別值,也會反映到instance2中。
以上是實例分析JavaScript原型鏈新增方法和出現的問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!