JavaScript基礎(chǔ)系列之——繼承

一、基本概念:

? ? JavaScript基于原型實現(xiàn)面向?qū)ο筇匦裕贘S編程中,面向?qū)ο蟮睦^承是重點,本文將從簡單開始介紹JS的繼承。


二、繼承方式:

1、借助構(gòu)造函數(shù)實現(xiàn)繼承:

function Parent1(){

? ? this.name = 'parent1'

}

function Child1(){

? ? Parent1.call(this)

? ? this.type = 'child1'

}

? ? 父級構(gòu)造函數(shù)在子級構(gòu)造函數(shù)內(nèi)使用call、apply方法,將自身的this指向子級實例,并執(zhí)行,從而使得子級實例后擁有父級的屬性;

? ? 簡單,但是父級原型上的屬性無法繼承;

2、借助原型鏈繼承:

function Parent2(){

? ? this.name = 'parent2';

}

function Child2(){

? ? this.type = 'Child2';

}

Child2.prototype = new Parent2();

console.log(new Child2());

? ? Child2構(gòu)造函數(shù)的屬性prototype指向一個原型對象,可以任意更改,將 Parent2 的實例作為Child2的原型對象,于是,當 new Child2 后生成的實例, 其 __proto__ 指向的原型對象就是 Child2的prototype指向的Parent2實例

? ? 這樣,子實例共享同一個繼承的實例的屬性,更改其中之一,會改變所有;沒有隔離;

3、組合繼承:

function Parent3(){

? ? this.name = 'parent3';

? ? this.play = [1,2,3,4];

}

function Child3(){

? ? Parent3.call(this);

? ? this.type = 'child3';

}

Child3.prototype = new Parent3();

var c31 = new Child3();

var c32 = new Child3();

c31.play.push(5);

console.log(c31, c32);

console.log(c31.constructor)

? ? 彌補了構(gòu)造函數(shù)和原型鏈繼承的缺點, 但是,父級構(gòu)造函數(shù)體執(zhí)行了兩次,生成的實例無法判斷實例源(實例的constructor屬性指向父級的構(gòu)造函數(shù))。(詳細見組合優(yōu)化1)

4、組合繼承的優(yōu)化1:

function Parent4(){

? ? this.name = 'parent4';

? ? this.play = [1,2,3,4];

}

function Child4(){

? ? Parent4.call(this);

? ? this.type = 'child4';

}

Child4.prototype = Parent4.prototype;

var c41 = new Child4();

var c42 = new Child4();

c41.play.push(5);

console.log(c41, c42);

console.log(c41 instanceof Child4, c41 instanceof Parent4); // true true

console.log(c41.constructor); // 指向 Parent4

? ? 彌補了組合繼承 執(zhí)行 2次的缺點, 但是,生成的實例,使用instanceof 判斷的時候,無法判斷該對象是由Parent5實例化或Child5實例化 , 使用實例的constructor屬性(實際為__proto__指向原型對象上的屬性),指向 Parent5.... 于是無法判斷該實例是由哪個構(gòu)造函數(shù)實例化的;(組合繼承都有這個缺點)

5、組合繼承的優(yōu)化2:

function Parent5(){

? ? this.name = 'parent5';

? ? this.play = [1,2,3,4];

}

function Child5(){

? ? Parent5.call(this);

? ? this.type = 'child5';

}

Child5.prototype = Object.create(Parent5.prototype); // 創(chuàng)建中間對象

Child5.prototype.constructor = Child5; // 中間對象的構(gòu)造函數(shù)更改constructor

var c51 = new Child5();

var c52 = new Child5();

c51.play.push(5);

console.log(c51, c52);

console.log(c51 instanceof Child5, c51 instanceof Parent5);

console.log(c51.constructor);

? ? 彌補了前面繼承方式的缺點;完美~~~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容