不會JS中的OOP,你也太菜了吧!(第二篇)

1、你必須知道的

1> 原型及原型鏈在繼承中起到了關鍵的做用。因此你必定要理解他們。
2> 不會JS中的OOP,你也太菜了吧!(第一篇)html

 

2、繼承的6種方法

1> 原型鏈繼承

原型鏈繼承是經過建立Super的實例,並將該實例賦值給Sub.prototype來實現的。函數

實現的本質是:重寫子類型的原型對象,代之以超類型的實例。this

function Super(){
    this.name = 'JChen___';
}
Super.prototype.getSuperName = function(){
    return this.name;
}

function Sub(){
    this.subname = 'JChen___son';
}
Sub.prototype = new Super(); //原型繼承體如今這裏
Sub.prototype.getSubName = function(){
    return this.subname;
}

var instance = new Sub();

注意:此時instance.constructor如今指向的是Super的,這是由於Sub.prototype指向了Super.prototype,而Super.prototype.constructor = Super。spa

原型鏈的問題:相似於利用原型建立對象,原型共享的特性也是原型鏈繼承的最大問題。prototype

 

2> 借用構造函數繼承

在解決原型中包含引用類型值所帶來的問題的過程當中,咱們開始使用一種叫作借用構造函數的技術。code

這種技術的基本思想至關簡單:在子類型構造函數的內部調用超類型構造函數htm

這樣一來,就會在新子類對象上執行超類函數中定義的全部對象初始化代碼。結果,每一個子類的實力都會有本身的超類中屬性的副本了。對象

function Super2(name){
    this.colors = ['red', 'blue'];
    this.name = name;
}

function Sub2(){
    Super2.call(this, 'JChen___2'); //借用構造函數技術體如今這裏 this.age = 29;
}

var instance1 = new Sub2();
instance1.colors.push('black');
var instance2 = new Sub2();
instance2.colors.push('green');

藉助構造函數繼承的問題:blog

1): 方法都在構造函數中定義,沒法複用。繼承

2): 在超類型的原型中的方法對子類是不可見的。

 

3> 組合繼承(原型+借用構造)

組合繼承指的是將原型鏈和借用構造函數的技術組合到一塊,從而發揮兩者之長的一種繼承模式。

組合繼承的思路:使用原型鏈實現對方法和屬性的繼承,經過借用構造函數實現對實例屬性的繼承。

function Super3(name){
    this.name = name;
    this.colors = ['red', 'blue'];
}
Super3.prototype.sayName = function(){
    return this.name;
}

function Sub3(name, age) {
    Super3.call(this, name);
    this.age = age;
}
Sub3.prototype = new Super3(); //解決借用構造函數技術的缺點
Sub3.prototype.constructor = Sub3; //糾正原型繼承改變了的構造函數
Sub3.prototype.sayAge = function(){
    return this.age;
}

組合繼承避免了原型鏈和借用構造函數的缺陷,融合了他們的優勢,成爲JavaScript中最經常使用的繼承模式。

組合繼承的問題:兩次調用超類構造函數。

 

4> 原型式繼承

原型式繼承的思路:藉助原型能夠基於已有的對象建立新對象,同時還沒必要所以建立自定義類型。

function object(o){ //原型式繼承的關鍵
    function F(){}
    F.prototype = o;
    return new F();
}
var person = {
    name: 'JChen___4',
    colors: ['blue']
}
var person1 = object(person);
person1.name = 'JChen___4___2'
person1.colors.push('red');
var person2 = object(person);
person2.name = 'JChen___4___3';
person2.colors.push('green');

原型式繼承的問題:同原型鏈同樣,他也有共享的劣勢。

 

5> 寄生式繼承

寄生式繼承的思路:建立一個僅用於封裝繼承過程的函數,該函數內部以某種方式來加強對象,最後再返回該對象

function createAnother(origin){ //寄生式繼承的關鍵
    var clone = object(origin);
    clone.sayHi = function(){
        return 'Hi';
    };
    return clone;
}
var person = {
    name: 'JChen___4',
    colors: ['blue']
}
var person1 = createAnother(person);

寄生式繼承的問題:像構造函數同樣,因爲不能作到函數的複用而下降效率。

 

6> 寄生組合式繼承

寄生組合式繼承:經過借用構造函數來借用屬性,經過原型鏈的混成形式來繼承方法。

其背後的思想是:沒必要爲了指定子類型的原型而調用超類型的構造函數,咱們須要的無非就是超類型的一個副本而已。

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}
function inheritProto(subType, superType){ //避免第一調用構造函數的關鍵
    var proto = object(superType.prototype);
    proto.constructor = subType;
    subType.prototype = proto;
}

function Super6(name){
    this.name = name;
    this.colors = ['red', 'blue'];
}
Super6.prototype.sayName = function(){
    return this.name;
}

function Sub6(name, age){
    Super6.call(this, name);
    this.age = age;
}

inheritProto(Sub6, Super6);

Sub6.prototype.sayAge = function(){
    return this.age;
}

var instance1 = new Sub6('JChen___6', '12');
instance1.colors.push('black');

開發人員廣泛認爲寄生組合式繼承是引用類型最理想的繼承範式。

 

3、總結

這就是JavaScript中的6種繼承方式,若是你們可以畫出每一個繼承的原型鏈關係圖,那麼繼承就是小菜一碟了。

相關文章
相關標籤/搜索