標籤:
原型鏈用於ECMAScript的繼承。其思想是利用原型讓一個參考型別繼承另一個參考型別的屬性和方法。說人話,我們知道,一個建構函式Subtype,其原型對象有一個指向建構函式的指標,這是聯絡建構函式和原型的橋樑,如果我讓原型對象的指標指向了另一個原型,而另一個原型原本指向其建構函式的指標也指向了另一個原型,那麼,這就是一個原型鏈了,原型上的屬性會一層一層往下傳遞。
function SuperType(){ this.property=true; } SuperType.prototype.getSuperValue=function(){ return this.property; }; function SubType(){ this.subproperty=false; } //subtype繼承了supertype的prototype SubType.prototype=new SuperType(); SubType.prototype.getSubValue=function(){ return this.subproperty; }; var instance=new Subtype(); alert(instance.getSuperValue());//true;
所以,繼承的實現本質是重寫了原型對象。
上面代碼中,最後輸出了true,原理是:以讀模數式訪問一個執行個體屬性或方法,現在instance中搜尋,搜尋不到就沿著原型鏈往上尋找,instance->Subtype.prototype->SuperType.prototype。如果找不到返回undefined.
在JS物件導向(1)中我們已經說到原型鏈的問題,也就是原型屬性是可以被所有執行個體共用的。解決這個問題的方法可以是借用建構函式,JS進階程式設計上的解釋是這種技術的基本思想是:在子類型建構函式的內部調用超類型的建構函式,函數是在特定環境中執行代碼的對象,可以通過使用apply()和call()方法在新建立的對象上執行建構函式。這話說的我一愣一愣的0.0
1 function SuperType(){ 2 this.color=[‘aa‘,‘bb‘]; 3 } 4 5 function SubType(){ 6 SuperType.call(this); 7 }//繼承了SuperType. 8 9 var instance1=new SuperType();10 var instance2=new SuperType();11 instance1.color.push(‘cc‘);12 alert(instance2.color)//[‘aa‘,‘bb‘];沒有因為instance1執行個體修改了color屬性而被影響。
1、call可以擴充函數的範圍。
2、call可以傳遞參數。
第6行的SuperType.call(this),在new SubType時,即建立新對象時,同時執行SuperType建構函式,而且其中的this指向的是執行個體instance1或者instance2。因此每個執行個體都會有自己的colors副本。
call傳遞參數如下
function SuperType(name){ this.color=[‘aa‘,‘bb‘]; this.name=name; } function SubType(name){ SuperType.call(this,name); this.age=20;}//繼承了SuperType.var instance1=new SubType(‘a‘);var instance2=new SubType(‘b‘);instance1.color.push(‘cc‘);alert(instance2.color);//[‘aa‘,‘bb‘]alert(instance2.age);//20alert(instance2.name);//b;
組合繼承 :使用原型鏈實現對原型屬性和方法的繼承(共用),使用建構函式實現對執行個體屬性的繼承(獨立)。
function SuperType2(name){ this.name=name; this.colors=[‘red‘,‘green‘]; } SuperType2.prototype.sayName=function(){ alert(this.name);//prototype的方法會共用給執行個體 }; function SubType2(name,age){ //繼承屬性 SuperType2.call(this,name);//借用超類型的建構函式 使每個subtype的執行個體擁有獨立的colors副本,可以修改colors而不會影響其他執行個體的colors this.age=age; } //繼承方法 SubType2.prototype=new SuperType2();//SuperType2的執行個體賦值給SubType2原型 SubType2.prototype.constructor=SubType2; SubType2.prototype.sayAge=function(){ alert(this.age); }; /*SubType2.prototype={ sayAge:function(){ alert(this.age); } };*/ var instance3=new SubType2(‘nick‘,20); var instance4=new SubType2(‘jack‘,30); instance3.colors.push(‘black‘); alert(‘組合繼承 age:‘+instance3.age);//20 alert(‘instance3自己修改後的的colors:‘+instance3.colors);//[‘red‘,‘green‘,‘black‘]; alert(instance3.name);//nick instance3.sayName();//nick instance3.sayAge();//20 instance4.sayName();//jack instance4.sayAge();//30
SuperType2的執行個體賦值給SubType2原型,兩個不同的instance3和instance4執行個體擁有自己的屬性,name/color/age等,還可以有相同的方法sayAge() sayName()。
組合繼承是最常用的繼承模式,除此之外還有許多的模式,如原型式繼承、寄生式繼承等。
JS物件導向(2)——原型鏈