Js實現繼承的幾種方式


一、原型鏈實現繼承

 原型鏈實現繼承的思想:利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。

 原型鏈的基本概念:  當一個原型對象等於另一個類型的實例,此時的原型對象將包含一個指向另一個指向另一個原型的指針。同時,另一個原型中也包含着一個指向另一個構造函數的指針。如果另一個原型是另一個類型的實例,此時實例和原型就構成了原型鏈

function SuperType(){ this.property=true; } SuperType.prototype.getSuperValue=function(){ return this.property; } function SubType(){ this.subproperty=false; } //通過創建SuperType的實例繼承了SuperType
SubType.prototype=new SuperType();  SubType.prototype.getSubValue=function(){ return this.subproperty; } var instance=new SubType(); alert(instance.getSuperValue()); //true                                      

對於代碼的解釋:

首先定義了兩個類型SuperType和SubType。此時SubType通過創建SuperType的實例(new SuperType()),並將該實例(new SuperType())賦給了SubType的原型SubType.prototype的方式   繼承了 SuperType。

此時存在於SuperType中實例中的所有屬性和方法,也存在於SubType.prototype中。此時,實例、原型和構造函數之間的關系如下圖所示。

 SubType的實例instance指向SubType的原型SubType.prototype,SubType.prototype又指向SuperType的原型。

注意:getSuperValue()方法仍然還在SuperType.prototype中,但property則位於SubType.prototype中。這是因為property是一個實例屬性,而getSuperValue()則是一個原型方法。

原型鏈存在的問題:

  1)包含引用類型值的原型屬性會被所有實例共享,這會導致對一個實例的修改會影響另一個實例。在通過原型來實現繼承時,原型實際上會變成另一個類型的實例。原先的實例屬性就變成了現在的原型屬性

(2)在創建子類型的實例時,不能向超類型的構造函數中傳遞參數

二、借用構造函數實現繼承

借用構造函數基本思想,即在子類型構造函數的內部調用超類型構造函數。函數只不過是在特定環境中執行代碼的對象,因此通過使用apply()和call()方法可以在新創建的對象上執行構造函數。

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,bllue,green,black

var instance2=new SubType(); alert(instance2.colors); //red,blue,green

代碼的解釋:

 SuperType.call(this);“借調”了超類型的構造函數。通過使用call()方法(或者apply()方法),在新創建的SubType實例的環境下調用了SuperType構造函數。這樣一來就會在新的SubType對象上執行SuperType()函數中定義的所有對象初始化代碼。結果,SubType的每個實例都會有自己的colors屬性副本

借用構造函數的優勢:可以在子類型構造函數中向超類型構造函數傳遞參數

 

function SuperType(name){ this.name=name; } function SubType(){ //繼承了SuperType,同時還傳遞了參數
      SuperType.call(this,"mary");//this(SubType的實例)調用SuperType構造函數 //實例屬性
      this.age=22; } var instance=new SubType(); alert(instance.name); //mary
alert(instance.age);  //29

 

借用構造函數的問題:

1)無法避免構造函數模式存在的問題,方法都在構造函數中定義,因此無法復用函數。

2)在超類型的原型中定義的方法,對子類型而言是不可見的。因此這種技術很少單獨使用

三、組合繼承

組合繼承:指的是將原型鏈和借用構造函數的技術組合到一起。思路是使用原型鏈實現對原型方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。這樣,既通過在原型上定義方法實現了函數的復用,又能夠保證每個實例都有它自己的屬性。

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("mary", 22); instance1.colors.push("black"); alert(instance1.colors); //red,blue,green,black
instance1.sayName();  //mary
instance1.sayAge();  //22

var instance2=new SubType("greg", 25); alert(instance2.colors); //red,blue,green
instance2.sayName();  //greg
instance2.sayAge();  //25

代碼解釋:

  SuperType構造函數定義了兩個屬性:name和colors。SuperType的原型定義了一個方法sayName()。

  SubType構造函數在調用SuperType構造函數時傳入了name參數。並定義了自己的屬性age。

然后,將SuperType實例賦值給SubType的原型,然后又在新原型上定義了sayAge方法。
此時可以讓兩個不同的SubType實例分別擁有自己的屬性,又可以使用相同的方法

組合繼承的優勢:
避免了原型鏈和借用構造函數的缺點,融合了他們的優點,是JavaScript中最常用的繼承模式。instanceof和isprototypeOf()也能夠用於識別基於組合繼承創建的對象

 

 四、原型式繼承

 

五、寄生式繼承

 

六、寄生組合式繼承

參考文章:

 https://www.cnblogs.com/cjr001/p/7241553.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM