首頁  >  文章  >  web前端  >  javascript繼承方式詳解

javascript繼承方式詳解

高洛峰
高洛峰原創
2016-11-16 11:30:011089瀏覽

繼承方式主要有六種:

1、原型鏈繼承 存在物件共享的問題

2、建構子繼承 借助call apply方法實現 :函數復用性問題每次實例化,重新執行了一次父類,父類別中的方法重複定義 

3、組合模式(原型鏈+建構子)建構函式繼承屬性,原型鏈繼承方法 :解決了物件共享,但是屬性繼承出現兩次

4、原型方式使用一個空間空函數

5、寄生方式 在原型方式上增加額外了方法

6、寄生組合方式(解決了屬性繼承出現2次的問題)

1、原型鏈方式

子類別在繼承父類時,是將子類別的prototype指向父類別的一個實例物件。 當子類別實例化時,所有子類別的實例都會共用父類別的那個實例上(假設叫做p)的屬性和方法,如果p上有引用型的屬性,則子類別的實例可以修改該引用型的屬性,導致其他實例上的該屬性也被修改。

//原型链方式
function A(){
    this.name = 'lc';
    this.stus = ['a','b','c'];
}
A.prototype.introduce = function (){
    alert(this.name);
}
 
function B(){}
B.prototype = new A();
 
var s1 = new B();
var s2 = new B();
console.log(s1.stus);  //['a','b','c']  
s1.stus.push('d');     //改变s1上的属性,会影响s2上的该属性
console.log(s2.stus);  // ['a','b','c','d']

如果改成下面的,則不會影響。

//原型链方式
function A(){
    this.name = 'lc';
    this.stus = ['a','b','c'];
}
A.prototype.introduce = function (){
    alert(this.name);
}
 
function B(){}
B.prototype = new A();
 
var s1 = new B();
var s2 = new B();
 
s1.stus = ['d'];   //在s1上增加了属性,  就近原则,不在查找原型链上的同名属性
console.log(s1.stus);  //['d']
console.log(s2.stus);  // ['a','b','c']

2、構造函數方式繼承

  共用構造函數,方法都是在內部定義,複函復用性問題無從談起。

//构造函数方式继承
function A(name){
    this.name = name;
    this.type = 'parent';
    this.introduce = function (){ alert(this.name);}
}
A.prototype.sayhi = function (){
    alert(this.type);
}
function B(name,age){
    A.call(this,name);  //使用call方法 实现继承 但是父类中的方法重复定义 无复用性
    this.age = age;
    this.introduce = function (){ alert(this.name+this.age);}
}
 
var b = new B('lc',25);
b.introduce(); //lc25
b.sayhi();  //parent

3、混合方式(原型方式+構造函數方式) 

使用構造函數繼承屬性,原型鏈繼承方法

但是有一點不好的地方:  使用原型鏈繼承時,實際上屬性也繼承了,重複了。 

function A(name){
    this.name = name;
    this.type = 'parent';
}
A.prototype.sayhi = function (){
    alert(this.type);
}
function B(name,age){
    A.call(this,name);
    this.age = age;
    this.introduce = function (){ alert(this.name+this.age);}
}
B.prototype = new A();

4、原型式繼承

使用了一個中間空函數,實現繼承後,回傳一個物件。

function extend(parent){
    function F(){}
    F.prototype = parent;
    return new F();
}

 5、寄生式繼承 在原型式的基礎上,再為物件添加屬性方法

function extend(parent){
    function F(){}
    F.prototype = parent;
    return new F();
}
 
function createObj(p){  
    var clone = extend(p);
    clone.name = 'hello';    
    clone.say = function (){}
    return clone;
}

6、寄生組合式繼承

在繼承方法的時候,不再實例化父類型的建構函數,而是使用inheritPrototype方法. 使用一個中間空函數,讓這個空函數去繼承父類別原型,然後實例化這個空函數(繼承了父類別prototype中的所有方法)。將子類別的原型指向這個實例化的空物件即可。

避免了實例化父類別的建構子。

/* 寄生组合式继承 */
function inheritPrototype(subType, superType) {
  // var obj= extend(superType.prototype);
  function F(){}
  F.prototype = superType.prototype;
  var obj= new F();
 
  //obj.constructor = subType;
  subType.prototype = obj;    //不可将subType的prototype直接指向superType,否则的话,对子类prototype的修改会反应到父类上,  引用型变量
  subType.prototype.constructor = subType;
}

物件冒充: 使用建構子的方式宣告類,將一個類別的方法指向另一個建構函式(因為建構子本身就是一個方法函式),實作繼承

function A(){
    this.name = {name1:'hello'};
    this.say = function (){ console.log(this.name);}
}
function B(){
    this.method = A;
    this.method();
    delete this.method;
}
 var bObj = new B();


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn