看了都知道繼承也就那麼回事兒

Aemple發表於2018-04-18

看了都知道繼承也就那麼回事兒

前言

各位大佬們都來了就花點時間看看吧 看了之後來個小心心吧 不然沒有動力繼續寫下去呀 哈哈

開始

預備知識

原型鏈知識---話不多說先上圖,一圖勝千言

看了都知道繼承也就那麼回事兒
現在來寫一個基本的函式例項來解釋這幅圖

function Test () {
    this.name = 'test'; 
}
var fn = new Test;
console.log(fn.name);
//我們稱Test為建構函式  fn為建構函式Test的例項
//Test的prototype(原型)和例項的__proto__(原型)都指向了原型同一個原型物件  
//原型物件的constructor指向了建構函式
複製程式碼

Object.create 再來一張圖片很清晰的解釋它的作用

看了都知道繼承也就那麼回事兒
下面開始玩轉繼承

第一類 最簡單的繼承---原型繼承

// 原型繼承
function A() {
    this.x = 'test';
}

A.prototype.getX = function () {
    console.log(this.x);
    
};

function B() {
    this.y = 'test2';
}

B.prototype = new A;
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test
複製程式碼

總結

這樣就實現了B的例項fn繼承了父類(A)中的所有屬性和方法。我們把A自己的屬性和方法(x)叫做私有屬性,父類(A)原型上的方法和屬性(getX)叫做公有屬性這種繼承方式就是把父類(A)的公有屬性和私有屬性都繼承到了子類(B)的公有屬性中

優點:簡單實用

缺點:因為只是改變了prototype的指向導致constructor都指向了A,且都變成了自己的公有屬性

改進方法

// 原型繼承
function A() {
    this.x = 'test';
}

A.prototype.getX = function () {
    console.log(this.x);
    
};

function B() {
    this.y = 'test2';
}

B.prototype = new A;
B.prototype.constructor = B;//手動改變constructor
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test
複製程式碼

第二種 利用call改變this指向---call繼承

// call繼承
function A() {
    this.x = 'test';
}

A.prototype.getX = function () {
    console.log(this.x);

};

function B() {
    this.y = 'test2';
    A.call(this);
}

var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
複製程式碼

總結

這樣就實現了B的例項fn繼承了A中的私有屬性和方法。這種繼承方式就是把A的私有有屬性繼承到了B的私有屬性中

優點:簡單

缺點:只能繼承父類的私有屬性

第三種 複製屬性實現繼承---冒充物件繼承

//冒充物件繼承
function A() {
    this.x = 'test';
}

A.prototype.getX = function () {
    console.log(this.x);

};

function B() {
    this.y = 'test2';
    var temp = new A;
    for (key in temp) {
        // this=>例項fn
        this[key] = temp[key];
    }
    temp = null;
}
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
複製程式碼

總結

這樣就實現了B的例項fn繼承了A中的私有屬性和方法。這種繼承方式就是把A的私有有屬性繼承到了B的私有屬性中

缺點:只能繼承父類的私有屬性

第四種 混合模式繼承

//混合模式繼承
function A() {
    this.x = 'test';
}

A.prototype.getX = function () {
    console.log(this.x);

};

function B() {
    this.y = 'test2';
    A.call(this);
    
}

B.prototype = new A;
B.prototype.constructor = B;//手動改變constructor
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test
複製程式碼

總結

這樣就實現了B的例項fn繼承了A中的所有屬性和方法。這種繼承方式就是把父類(A)的公有屬性和私有屬性都繼承到了子類(B)的公有屬性中並且把父類的私有屬性繼承到了子類的私有屬性中

優點:很全面

缺點:因為只是改變了prototype的指向導致constructor都指向了父類(A),複製了兩份父類的私有屬性

第五種 Create繼承模式

//Create模式繼承
function A() {
    this.x = 'test';
}

A.prototype.getX = function () {
    console.log(this.x);

};

function B() {
    this.y = 'test2';
    A.call(this);

}

B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;//手動改變constructor
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test

複製程式碼

總結

這樣就實現了B的例項fn繼承了A中的所有屬性和方法。**這種繼承方式就是把父類(A)的公有屬性和私有屬性分別都對應繼承到了子類(B)的公有屬性和私有屬性中。

優點:很全面

缺點:Obiect.create 方法不支援IE 6 7 8

改進為相容版本

//Create模式繼承  相容
function A() {
    this.x = 'test';
}

A.prototype.getX = function () {
    console.log(this.x);

};

function B() {
    this.y = 'test2';
    A.call(this);

}

B.prototype = myCreate(A.prototype);
B.prototype.constructor = B;//手動改變constructor
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test

function myCreate (o) {
    function fn () {}
    fn.prototype = o ;
    return new fn;
}
複製程式碼

總結

每種方式都有優點和缺點,推薦想簡單使用第一種但最好使用最後一種。

看了都知道繼承也就那麼回事兒

寫文章不容易希望各位小哥哥、小姐姐、大佬們給個小心心吧。

相關文章