JavaScript中的繼承

JavaScript中的繼承是經過原型鏈實現的,有幾種設計繼承的方法總結以下:app

一. 原型鏈函數

  基本思想:每一個構造函數都有一個原型對象,原型對象又都包含一個指向構造函數的指針,而實例又指向一個原型對象的指針,那麼,若是咱們讓原型對象等於另外一個類型的實例,此時的原型對象將包含一個指向另外一個原型的指針,相應的另外一個原型中也包含着一個指向另外一個構造函數的指針,假如另外一個原型又是另外一個類型的實例呢,那麼上述的關係依然成立,如此層層遞進,就構成了實例和原型的鏈條。下面是例子this

 1 function SuperType(){
 2     this.property = true;
 3 }
 4 SuperType.prototype.getSuperValue = function(){
 5     return this.property;
 6 }
 7 function SubType(){
 8     this.subproperty = false;
 9 }
10 //繼承SuperType
11 SubType.prototype = new SuperType();
12 SubType.prototype.getSubValue = function(){
13     return this.subproperty;
14 };
15 var instance = new SubType();
16 alert(instace.getSuperValue());//true

缺點:引用類型值的屬性會被全部實例共享,假設有兩個子類型的實例,其中一個實例修改了從超類型繼承而來的引用類型的值,修改的結果也一樣會在另外一個實例中顯示出來;spa

        建立子類型的實例的時候,不能向超類型的構造函數中傳遞參數。prototype

二.借用構造函數設計

     基本思想:在子類型構造函數的內部調用超類型構造函數,即經過apply和call方法來調用構造函數指針

 1 function SuperType(){
 2    this.colors = ["red","blue","green"];
 3 }
 4 function SubType(){
 5    //繼承了SuperType
 6    SuperType.call(this);
 7 }
 8 var instance1 = new SubType();
 9 instance1.colors.push("black");
10 alert(instance1.colors);//"red,blue,green,black"
11 var instance2 = new SubType();
12 alert(instance2.colors);//"red,blue,green"

優勢:解決了原型中包含引用類型值所帶來的問題code

缺點:超類型的原型中定義的方法,對子類型而言也是不可見的(沒有指向超類型原型的指針,只有指向構造函數的),結果全部類型都只能使用構造函數模式,這樣確定是很差的。對象

三.組合繼承blog

基本思想:使用原型鏈實現對原型屬性和方法的繼承,經過借用構造函數來實現對實例屬性的繼承下面是例子

 1 function SuperType(name){
 2   this.name = name;
 3   this.colors = ["red","blue","green"];
 4 }
 5 SuperType.prototype.sayName = function(){
 6   alert(this.name);
 7 };
 8 function SubType(name,age){
 9   //繼承屬性
10   SuperType.call(this,name);
11   this.age = age;
12 }
13 //繼承方法
14 SubType.prototype = new SuperType();
15 SubType.prototype.constructor = SubType;
16 SubType.prototype.sayAge = function(){
17   alert(this.age);
18 };
19 var instance1 = new SubType("Nicholas",29);
20 instance1.colors.push("black");
21 alert(instance1.colors);//"red,blue,green,black"
22 instance1.sayName();//"Nicholas"
23 instance1.sayAge();//29
24 var instance2 = new SubType("Greg",27);
25 alert(instance2.colors);//"red,blue,green"
26 instance2.sayName();//"Greg"
27 instance2.sayAge();//27

組合繼承是最經常使用的繼承模式,並且,利用instanceof 和isprototypeof()也可以用於識別基於組合繼承建立的對象

四.原型式繼承

基本思想:藉助原型能夠基於已有的對象建立新對象,同時,沒必要所以建立自定義類型。下面是例子

 1 function object(o){
 2   function F(){};
 3   F.prototype = o;
 4   return new F();
 5 }
 6 var person = {
 7   name:"Nicholas",
 8   friends:["shelby","Cour","Van"]
 9 };
10 var anotherPerson = object(person);
11 anotherPerson.name = "Greg";
12 anotherPerson.friends.push("Rob");
13 var yetAnotherPerson = object(person);
14 yetAnotherPerson.name = "Linda";
15 yetAnotherPerson.friends.push("Barbie");
16 alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"

缺點:仍是包含引用類型值得屬性始終會共享相應的值,實例中修改會在原型中展示。

        不管什麼狀況下都會調用兩次超類型構造函數:一次是在建立子類型原型的時候,另外一次是在子類型構造函數內部,子類型最後會包含超類型中的所有實例屬性,但有時候咱們會在調用子類型構造函數時重寫這些屬性。

五.寄生式繼承

基本思路:與寄生構造函數和工廠模式相似,即建立一個僅用於封裝繼承過程的函數,該函數在內部以某種方式類加強對象。下面是例子:

 function object(o){
    function F(){};
    F.prototype = o;
    return new F();
 }
function createAnother(original){
  var clone = object(original);//經過調用函數來建立一個新對象
  clone.sayHi = function(){
     alert("hi");
  };
  return clone;
}
var person = {
  name:"Nicholas",
  friends:["Shelby","Court","Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();//"Hi"

使用場景:在主要考慮對象而不是自定義類型和構造函數的狀況下。

六.寄生組合式繼承

     爲了解決組合繼承的缺點

     基本思想:經過借用構造函數來繼承屬性,經過原型鏈的混成形式來繼承方法

function object(o){
    function F(){};
    F.prototype = o;
    return new F();
 }
function inheritPrototype(subType,superType){
  var prototype = object(superType.ptorotype);//建立對象
  prototype.constructor = subType;//加強對象
  subType.prototype = prototype;//指定對象
}

  可以正常使用instanceof() 和 isPrototypeOf()。

相關文章
相關標籤/搜索