JS繼承之借用構造函數(shù)繼承和組合繼承
借用構造函數(shù)繼承
在解決原型中包含引用類型值所帶來問題的過程中,開發(fā)人員開始使用一種叫做借用構造函數(shù)(constructor stealing)的技術(有時候也叫做偽造對象或經(jīng)典繼承)。這種技術的基本思想相當簡單,即在子類型構造函數(shù)的內部調用超類型構造函數(shù)。
基本模式
function SuperType(){ this.colors = ["red", "blue", "green"]; } function SubType(){ //繼承了SuperType SuperType.call(this); } 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"
基本思想
借用構造函數(shù)的基本思想就是利用call或者apply把父類中通過this指定的屬性和方法復制(借用)到子類創(chuàng)建的實例中。因為this對象是在運行時基于函數(shù)的執(zhí)行環(huán)境綁定的。也就是說,在全局中,this等于window,而當函數(shù)被作為某個對象的方法調用時,this等于那個對象。call 、apply方法可以用來代替另一個對象調用一個方法。call、apply 方法可將一個函數(shù)的對象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對象。
所以,這個借用構造函數(shù)就是,new對象的時候(注意,new操作符與直接調用是不同的,以函數(shù)的方式直接調用的時候,this指向window,new創(chuàng)建的時候,this指向創(chuàng)建的這個實例),創(chuàng)建了一個新的實例對象,并且執(zhí)行SubType里面的代碼,而SubType里面用call調用了SuperTyep,也就是說把this指向改成了指向新的實例,所以就會把SuperType里面的this相關屬性和方法賦值到新的實例上,而不是賦值到SupType上面。所有實例中就擁有了父類定義的這些this的屬性和方法。
優(yōu)勢
相對于原型鏈而言,借用構造函數(shù)有一個很大的優(yōu)勢,即可以在子類型構造函數(shù)中向超類型構造函數(shù)傳遞參數(shù)。因為屬性是綁定到this上面的,所以調用的時候才賦到相應的實例中,各個實例的值就不會互相影響了。
例如:
function SuperType(name){ this.name = name; } function SubType(){ //繼承了SuperType,同時還傳遞了參數(shù) SuperType.call(this, "Nicholas"); //實例屬性 this.age = 29; } var instance = new SubType(); alert(instance.name); //"Nicholas"; alert(instance.age); //29
劣勢
如果僅僅是借用構造函數(shù),那么也將無法避免構造函數(shù)模式存在的問題——方法都在構造函數(shù)中定義,因此函數(shù)復用就無從談起了。而且,在超類型的原型中定義的方法,對子類型而言也是不可見的,結果所有類型都只能使用構造函數(shù)模式??紤]到這些問題,借用構造函數(shù)的技術也是很少單獨使用的。
組合繼承
組合繼承(combination inheritance),有時候也叫做偽經(jīng)典繼承。是將原型鏈和借用構造函數(shù)的技術組合到一塊,從而發(fā)揮二者之長的一種繼承模式。/p>
基本思想
思路是使用原型鏈實現(xiàn)對原型屬性和方法的繼承,而通過借用構造函數(shù)來實現(xiàn)對實例屬性的繼承。這樣,既通過在原型上定義方法實現(xiàn)了函數(shù)復用,又能夠保證每個實例都有它自己的屬性。
基本模型
function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ //繼承屬性 SuperType.call(this, name); this.age = age; } //繼承方法 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); }; var instance1 = new SubType("Nicholas", 29); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" instance1.sayName(); //"Nicholas"; instance1.sayAge(); //29 var instance2 = new SubType("Greg", 27); alert(instance2.colors); //"red,blue,green" instance2.sayName(); //"Greg"; instance2.sayAge(); //27
優(yōu)勢
組合繼承避免了原型鏈和借用構造函數(shù)的缺陷,融合了它們的優(yōu)點,成為JavaScript 中最常用的繼承模式。
劣勢
組合繼承最大的問題就是無論什么情況下,都會調用兩次超類型構造函數(shù):一次是在創(chuàng)建子類型原型的時候,另一次是在子類型構造函數(shù)內部。雖然子類型最終會包含超類型對象的全部實例屬性,但我們不得不在調用子類型構造函數(shù)時重寫這些屬性。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
IE6,IE7,IE8下使用Javascript記錄光標選中范圍(已補全)
IE6,7,8下使用Javascript記錄光標選中范圍(已補全)(已解決單個節(jié)點內部重復字符的問題)2011-08-08