理解JavaScript繼承(一)

理解JavaScript繼承(一)

咱們都知道,面向對象的編程語言很是強大,之因此強大,就是其支持繼承。在JavaScript中,也支持繼承,並且有多種方法實現繼承,好比原型鏈繼承,借用構造函數繼承,或者把原型鏈和借用構造函數函數組合在一塊兒的組合繼承,還有直接原型式繼承,深淺拷貝繼承。下面我就一一來講一說這些繼承方法。javascript

1.原型鏈

首先咱們得清楚構造函數(constructor),原型對象(prototype)和實例的三者關係。html

每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針。java

function SuperType(){
    this.property = true;
}
        
SuperType.prototype.getSuperValue = function(){
    return this.property;
};
        
function SubType(){
    this.subproperty = false;
}
        
//inherit from SuperType
SubType.prototype = new SuperType();//重寫原型對象,賦值爲一個實例對象,得到實例對象的全部屬性和方法
        
SubType.prototype.getSubValue = function (){
    return this.subproperty;
};

var instance = new SubType();
alert(instance.getSuperValue());   //true

原型鏈的詳細請看深刻理解原型鏈一文編程

2.借用構造函數

function SuperType(){
    this.colors = ["red", "blue", "green"];
}

function SubType(){  
    //inherit from SuperType
    SuperType.call(this);
}

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

經過借用構造函數的方法,會實現對實例屬性的繼承,每一個實例都有它本身的屬性,這些屬性都是部署在本身身上的,每個實例對象都有本身的一個副本。改變屬性不會對其它實例對象的該屬性形成影響。數組

3.組合繼承

組合繼承,有時候也叫僞經典繼承,指的是將原型鏈和借用構造函數的技術組合到一塊,從而發揮兩者之長的一種繼承模式。其背後的思路是使用原型鏈實現對原型屬性和方法的繼承,而經過借用構造函數來實現對實例屬性的繼承。這樣既經過在原型上定義方法實現了函數複用,又可以保證每一個實例都有它本身的屬性。編程語言

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.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`

4.原型式繼承

原型式繼承並無使用嚴格意義上的構造函數,而是藉助原型能夠基於已有的對象建立新對象,同時還沒必要建立自定義類型。函數

function object(o) {
    function F() {}    
    F.prototype = o;  
    return new F();
}

在object()函數內部,先建立了一個臨時性的構造函數,而後將傳入的對象做爲這個構造函數的原型,最後返回了這個臨時類型的一個新實例。本質上,是對傳入其中的對象作了一次淺拷貝。this

實例prototype

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}
        
var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
        
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
        
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
        
alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"

原型式繼承要求你必須有一個對象做爲另外一個對象的基礎,經過把一個對象傳遞給object()函數,而後再根據具體需求對獲得的對象加以修改(修改原來的,或者添加新的屬性方法)便可。指針

在ECMAScript5中,新增了一個Object.create()方法規範了原型式繼承,這個方法接受兩個參數:一個用做新對象原型的對象和(可選的)一個爲新對象定義額外屬性的對象。在傳入一個參數的狀況下,Object.create()與object()方法的行爲相同。

實例

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
        
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
        
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");

alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
相關文章
相關標籤/搜索