javascript的組合繼承

2021-09-23 15:41:57 字數 2771 閱讀 5538

需要先說明一點,這篇部落格是基於高程來寫的,這裡只是加上自己的理解而已。

function supertype() 

supertype.prototype.sayname = function()

function subtype() {}

subtype.prototype = new supertype()

var instance1 = new subtype()

instance1.colors.push('black')

alert(instance1.colors) // ['red', 'blue', 'green', 'black']

var instance2 = new subtype()

alert(instance2.colors) // ['red', 'blue', 'green', 'black']

這段**是高程上的例子,如果有翻過書的讀者應該是有印象的,對於沒有讀過的讀者,我就在這裡解釋一下這段**說了什麼。

首先我們定義了乙個supertype的建構函式,並且有個屬性colors,是乙個陣列型別的物件。之後通過

supertype.prototype.sayname = function()
給supertype的原型物件繫結了乙個sayname方法。之後又定義了乙個subtype的建構函式。接下來這一行**很重要

subtype.prototype = new supertype()
所以當我們下面利用建構函式subtype建立例項的時候,這個例項物件才可以使用colors這個屬性。

然後看到注釋,發現當我們只對instance1這個例項去修改colors的時候,卻發現instance2的colors也被改變了。這顯然不太合適,因為在寫**的時候,我們希望這兩個例項可以擁有自己的屬性,並且我們發現,在進行例項化的時候,我們沒有辦法對父類進行傳參,也就是沒辦法對supertype這個建構函式傳遞引數,那麼我們怎麼樣做呢?

前人搞了乙個借用建構函式的方法,具體怎麼用,我們還是看高程裡面的例子,我也依然會進行分析。

function supertype(name) 

supertype.prototype.sayname = function()

function subtype(name, age)

subtype.prototype = new supertype()

subtype.prototype.constructor = subtype

subtype.prototype.sayage = function()

var instance1 = new subtype('nicholas', 29)

instance1.colors.push('black')

alert(instance1.colors)

instance1.sayname()

instance1.sayage()

var instance2 = new subtype('greg', 27)

alert(instance2.colors)

instance2.sayname()

instance2.sayage()

我們看一下這個**,其中需要注意的是subtype中的**,裡面寫了supertype.call(this, name)這樣一句**,這是幹嘛呢?沒錯,這個東西就是上面提到的借用建構函式。有js基礎的應該知道call是用來做什麼的,這裡在subtype裡面通過supertype.call(this, name),這個地方實際上就相當於subtype呼叫了父類的建構函式,並且讓this指向subtype,而supertype有乙個colors屬性,間接的subtype的例項也會擁有這個colors屬性。那麼這種方式跟前一種方式有什麼不同呢,其實區別是很明顯的,當我們通過subtype建立例項的時候,都會呼叫supertype獲得乙個新的colors,方法跟原型物件是不同的,原型物件的屬性只有乙份,而方法中的屬性每次呼叫都會生成乙個新的屬性,因此,通過這樣的方式,我們也就做到了每個例項都擁有了自己的屬性colors,這個時候再去改變這個colors就不會影響到另外乙個例項的colors屬性了。

我們還看到supertype.call(this, name)裡面我們還傳入了乙個name引數。因此我們通過借用建構函式的方法實現了在建立子類物件的時候對父類物件進行傳參的操作了。

通過借用建構函式確實很好的解決了原型鏈帶來的問題,可是如果這樣的話,當我們每個例項都需要有自己的屬性的時候,我們不就都得將方法或者屬性寫到父類裡面然後借用建構函式了嗎,接著我們每次建立例項的時候又每次都要分配記憶體,原型的出現就是為了解決復用性的,結果這樣一搞復用性就沒了。顯然這是借用建構函式這個方法存在的乙個問題。

那麼重頭戲來了,我們發現不管是單獨使用原型鏈還是借用建構函式都沒辦法很好的解決問題,因此前人提出了組合繼承,也就是將原型鏈和借用建構函式兩種方法組合在一起。

還是上面那個例子。其實組合繼承很容易理解,對於屬性來說,用借用構造方法,對於一些同用的方法,就設定到原型物件上。

因為有些屬性必須要每個例項各自乙份,對於這種屬性就只能通過呼叫父類的建構函式來解決,對於上面的**,比如

sayname方法,就沒必要了,因為這種是所有例項通用的,就放到原型物件上。

其實感覺自己表達的很粗糙,但會慢慢加油的。如果有錯誤的地方,多謝指正,非常感謝。

JavaScript 繼承 組合繼承

繼承 組合繼承 組合繼承也叫做偽經典繼承,指的是將原型鏈和借用建構函式的技術組合到一塊,從而發揮二者之長的一種繼承模式。組合繼承的基本思路是使用原型鏈實現對原型屬性和和方法的繼承,而通過借用建構函式來實現對例項屬性的繼承。組合繼承通過在原型上定義方法實現了函式復用,又能夠保證每個例項都有它自己的屬性...

JavaScript 組合模式

如果您在通讀單例模式一節後,認為 嗨,這很簡單 那麼不要著急,我還有一些更加複雜的模式要討論,其中乙個就是組合模式。組合,顧名思義是指用包含多個部件的物件建立單一實體。這個單一實體將用作所有這些部件的訪問點,雖然這大大簡化了操作,但也可能具有相當的欺騙性,因為沒有哪種隱性方式明確表明該組合包含多少部...

javascript中的繼承

最常見的三種繼承方式 1.建構函式繼承 建構函式繼承 function people name function student school 例項方法 people.prototype.show function var stu new student 星星幼兒園 stu.name 小明 stu....