js的13種繼承

js繼承的13種方式

也可以說只有12種,ES6的extend 也是12種方法之一-寄生繼承的語法糖

1、原型鏈法

程式碼示例

Child.prototype = new Parent();

所屬模式:

1、基於構造器工作方式
2、使用原型鏈模式

技術註解

1、默認繼承機制
2、提示:我們可以將方法與屬性集中可重用的部分遷移到原型鏈中,而將不可重用的那部分設置為對象的自身屬性

詳細程式碼解釋

2、僅從原型鏈繼承法

程式碼示例

Child.prototypo = Parent.prototype

所屬模式

1、基於構造器工作模式
2、原型拷貝模式(不存在原型鏈,所有對象共享一個原型)

技術註解

1、由於該模式在構建繼承關係時不需要新建實例,效率上有較好的表現
2、原型鏈上的查詢也會比較快,因為這裡根本不存在鏈
3、缺點在於,對子對象的修改會直接影響其父對象

詳細程式碼註解

3、臨時構造器法

程式碼示例

function extend(Child, Parent){
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber =  Parent.prototype
}

所屬模式

1、基於構造器工作的模式
2、使用原型鏈模式

技術註解

1、此模式不同於1號方法,它只繼承父對象的原型屬性,而對其自身屬性(也就是被構造器添加到this值中的屬性)則不予繼承;
2、另外,該模式還為我們訪問父對象提供了便利的方法(通過uber 屬性)

詳細程式碼註解

4、原型屬性拷貝法

程式碼示例

function extend2(Child, Parent){
    var p = Parent.prototype;
    var c = Child.prototype;
    for(var i in p) {
        c[i] = p[i]
    }
    c.uber =  p
}

所屬模式

1、基於構造器工作的模式
2、使用原型鏈模式
3、拷貝屬性模式

技術註解

1、將父對象原型中的內容全部轉換成子對象原型屬性
2、無須為繼承單獨創建對象實例
3、原型鏈本身也更短

詳細程式碼註解

5、全屬性拷貝法(淺拷貝法)

程式碼示例

function extend2(p){
    var c = {};
    for(var i in p) {
        c[i] = p[i]
    }
    c.uber =  p
    return c
}

所屬模式

1、基於對象工作模式
3、拷貝屬性模式

技術註解

1、非常簡單
2、沒有使用原型屬性

詳細程式碼註解

6、深拷貝法

程式碼示例

let deepCopy = function (child, parent){
    var child = child || {};
    for(var i in parent) {
        if(typeof parent[i] === "object") { // 引用類型的判斷
            child[i] = Array.isArray(parent[i]) ? [] : {}; // child[i] 跟這個parent[i] 走
            deepCopy(child[i], parent[i]); 
        } else {
            child[i] = parent[i]
        }
    }
    return child;
}

所屬模式

1、基於對象工作模式
3、拷貝屬性模式

技術註解

1、非常簡單
2、沒有使用原型屬性
3、所有對象執行的都是值傳遞

詳細程式碼註解

7、原型繼承法

程式碼示例

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

所屬模式

1、基於對象工作模式
2、使用原型鏈模式

技術註解

1、丟開仿類機制,直接在對象之間構造繼承關係
2、發揮原型固有優勢

詳細程式碼註解

8、擴展與增強模式

程式碼示例

function objectPlus(o, stuff){
    var n ;
    function F(){};
    F.prototype = o;
    n = new F();
    n.uber = o;
    for(var i in stuff) {
        n[i] = stuff[i];
    }
    return n;
}

所屬模式

1、基於對象工作模式
2、使用原型鏈模式
3、屬性拷貝模式

技術註解

1、原型繼承法和屬性拷貝法的混合應用
2、它通過一個函數一次性完成對象的繼承和擴展

詳細程式碼註解

9、多重繼承法

程式碼示例

function multi(){
    var n = {}, stuff, j, len = arguements.length;
    for(j = 0; j < len; j++) {
        stuff = arguments[j];
        for(var i in stuff) {
            n[i] = stuff[i]
        }
    }
    return n
}

所屬模式

1、基於對象工作模式
2、屬性拷貝模式

技術註解

1、混合插入式繼承實現
2、它會按照父對象的出現順序一次對它們執行屬性全拷貝

詳細程式碼註解

10、寄生繼承法

程式碼示例

function parasite(){
    var that = Object.create(victim);
    that.more = 1;
    return that;
}

所屬模式

1、基於對象工作模式
2、使用原型鏈模式

技術註解

1、該方法通過一個類似構造器的函數來創建對象
2、該函數會執行相應的對象拷貝,並對其進行擴展,然後返回該拷貝

詳細程式碼註解

11、構造器借用法

程式碼示例

function Child(){
    Parent.apply(this, arguements)
}

所屬模式

1、基於構造器工作模式

技術註解

1、該方法可以只繼承父對象的自身屬性
2、可以與方法1結合使用,以便從原型中繼承相關內容
3、它便於我們的子對象繼承某個對象具體屬性(並且還有可能是引用類型屬性)時,選擇最簡單的處理方式

詳細程式碼註解

12、構造器借用與屬性拷貝

程式碼示例

function Child(){
    Parent.apply(this, arguements)
}
extend2(Child, Parent)

所屬模式

1、使用構造器工作模式
2、使用原型鏈模式
3、屬性拷貝模式

技術註解

1、該方法是構造器借用與屬性拷貝法結合體
2、允許我們在不重複調用父對象構造函數的情況下同時繼承其自身屬性和原型屬性

詳細程式碼註解

13、ES6 extend

程式碼示例

let Parent = function () {};

class Child extend Parent {
    constructor(){
        super(this)
    }
}

所屬模式

1、基於對象工作模式
2、使用原型鏈模式

技術註解

1、該方法是寄生繼承法的語法糖
2、可以用babel 將其轉化一下,就能看到它實際的工作模式(寄生繼承, Object.create(obj))

詳細程式碼註解

參考

《javascript面向對象編程指南》