JavaScript實現繼承的多種方式(ES5)

  1. 談起JS繼承,咱們首先來了解下什麼是原型以及什麼是原型鏈。在此若是JS基礎不是很紮實的人會有疑問:「原型不就是原型鏈嗎?」。不他們不同,他們的差異很大。那下面來解釋下他麼的區別。
  • ①:原型: 在JavaScript高級程序設計中給出的解釋是· 每個構造函數(對應的就是類函數)都有一個prototype屬性(強調下是屬性),這個prototype屬性會指向一個原型對象(強調下是對象)。該原型屬性指向的原型對象稱之爲原型
  • ②:原型鏈: 每個構造函數的原型屬性會鏈式指向原型對象,每一個原型對象都會有個constructor屬性會指向構造函數(未定義時默認指向構造函數)其中造成了一種鏈式結構,咱們稱之爲原型鏈。
  • 在此普及一個常識。全部的對象類的底層原型鏈最終會指向瀏覽器原生Object的原型。所以因此對象類都可調用Object的原型方法。如下貼圖舉個例子
2. 迴歸正題,對象繼承有幾種方式,都是如何實現的呢? 看一下詳解。
  • ①·構造繼承(固然構造繼承又有三種實現方式,以下)
借用構造函數(constructor stealing)的技術(有時候也叫作僞造對象或經典繼承)。這種技術的基本思想至關簡單,即在子類型構造函數的內部調用超類型構造函數。別忘了,函數只不過是在特定環境中執行代碼的對象,所以經過使用 apply()和 call()方法也能夠在(未來)新建立的對象上執行構造函數,以下所示
  • 冒充繼承
function Person(name,age){
       this.name = name ;
       this.age = age;
       this.showName = function(){
           console.log('我是'+name);
    }
}

/** 
 *  @description 以自身運行環境運行函數,這時函數內的this均指向Child,
 *  所以父類的屬性所有移植到子類中
 */
function Child(){
       //這三句代碼最關鍵
       this.temp = Person; //建立一個自身緩存函數並將父類構造賦值
       this.temp('李端','26');
       delete this.temp;//刪除緩存函數
}
var child = new Child();
child.showName();//我是李端複製代碼
  • 綁定this方式實現
function Person(name,age){
       this.name = name ;
       this.age = age;
       this.showName = function(){
           console.log('我是'+name);
    }
}

/** 
 *  @description 以自身運行環境運行函數,這時函數內的this均指向Child,
 *  所以父類的屬性所有移植到子類中
 */
function Child(){
       Person.bind(this)('李端','26'); //綁定this到Person運行環境執行函數
}
var child = new Child();
child.showName();//我是李端複製代碼
  • call的方式實現
function Person(name,age){
    this.name = name ;
    this.age = age;
    this.showName = function(){
        console.log('我是'+name);
    }
}
function Child(){
    Person.call(this,'李端','26');
};
var child = new Child();
child.showName();複製代碼
  • apply方式實現
function Person(name,age){
    this.name = name ;
    this.age = age;
    this.showName = function(){
        console.log('我是'+name);
    }
 }
 function Child(){
    Person.apply(this,['李端','26']);
 };
 var child = new Child();
 child.showName();複製代碼
  • ②·原型繼承
function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.sayHello = function(){
    alert('使用原型獲得'+this.name);
}
var per = new Person('李端','26');
per.sayHello();
//建立新對象並實現繼承
function Student(){};
Student.prototype = new Person('端瑞','23')
var stu = new Student();
stu.sayHello();複製代碼
  • ③·組合繼承(組合構造和原型方式實現繼承)
組合繼承(combination inheritance),有時候也叫作僞經典繼承,指的是將原型鏈和借用構造函數的技術組合到一塊,從而發揮兩者之長的一種繼承模式。其背後的思路是使用原型鏈實現對原型屬性和方法的繼承,而經過借用構造函數來實現對實例屬性的繼承。這樣,既經過在原型上定義方法實現了函數複用,又可以保證每一個實例都有它本身的屬性。下面來看一個例子
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 複製代碼
  • ④·寄生繼承
寄生式(parasitic)繼承是與原型式繼承緊密相關的一種思路,而且一樣也是由克羅克福德推而廣之的。寄生式繼承的思路與寄生構造函數和工廠模式相似,即建立一個僅用於封裝繼承過程的函數,該函數在內部以某種方式來加強對象,最後再像真地是它作了全部工做同樣返回對象。如下代碼示範了寄生式繼承模式。 在這個例子中,createAnother()函數接收了一個參數,也就是將要做爲新對象基礎的對象。而後,把這個對象(original)傳遞給 object()函數,將返回的結果賦值給 clone。再爲 clone 對象添加一個新方法 sayHi(),最後返回 clone 對象。能夠像下面這樣來使用 createAnother()函數:
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 inheritPrototype(subType, superType){
 var prototype = Object(superType.prototype); //建立對象
 prototype.constructor = subType; //加強對象
 subType.prototype = prototype; //指定對象
}

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;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
 alert(this.age);
}; 複製代碼
相關文章
相關標籤/搜索