JavaScript最全的繼承模式

//js各種繼承的分析;

function Parent(name,age){

this.name=name;

? ? ? this.age=age;

? ? ? this.money=100;

? ? ? this.fly=function(){

console.log('這是對象本身的fly方法');

? ? ? }

}

Parent.prototype.sex='male';

Parent.prototype.play=function(){

console.log('這是原型上面的play方法');

}

var parent=new Parent('父親',45);

//1:第一種:原型指向父類實例

?function Sub(name,age) {

? ? ?this.name=name;

? ? ?this.age=age;

?}

?Sub.prototype=new Parent('天劫','18');

var? sub=new Sub('小明',11);

?var? sub1=new Sub('小紅',12);

?console.log(sub instanceof Sub); true;

?console.log(sub instanceof Parent);true;

//? 優(yōu)點:

?這是一個非常純粹的繼承,實例是子類的實例,也屬于父級的實例,父類的屬性方法以及父類原型上添加的屬性或方法,子類都可以訪問得到;

?缺點:

?原型對象上的引用屬性,所有的實例都是共享的,即在一個實例上修改,所有的實例均跟著變化;

?不能同時繼承多個父類。

第二種:構(gòu)造函數(shù)

?function Sub(name,age) {

? ? ?Parent.apply(this);

? ? ?this.name=name;

? ? ?this.age=age;

?}

?var? sub=new Sub('小明',11);

?var? sub1=new Sub('小紅',12);

?console.log(sub instanceof Sub); true;

?console.log(sub instanceof Parent);false;

// 優(yōu)點:

?這種繼承方式解決了傳統(tǒng)繼承中共享引用屬性的問題;

?創(chuàng)建子類實例的時候可以向父級傳遞參數(shù);

?可以繼承多個父類;

// 缺點:

/只能繼承父類構(gòu)造函數(shù)里面的屬性方法,不會繼承父類原型上的屬性方法;

無法實現(xiàn)函數(shù)復(fù)用,每個子類都有父類實例的副本,影響性能;

?實例只是子類的實例不是父類的實例。

第三種:原型指向父類實例+構(gòu)造函數(shù)

?function Sub(name,age) {

? ? ?Parent.apply(this);

? ? ?this.name=name;

? ? ?this.age=age;

?}

Sub.prototype=new Parent('父親',45);

?var? sub=new Sub('小明',11);

?var? sub1=new Sub('小紅',12);

?console.log(sub instanceof Sub); true;

?console.log(sub instanceof Parent);true;

// 優(yōu)點:

?可以繼承多個父類;

?既可以繼承父類構(gòu)造函數(shù)里面屬性和方法,又可以繼承父類原型屬性和方法;

?函數(shù)可以復(fù)用;

?父類的引用值不會共享;

// 缺點:

?調(diào)用了兩次父類的構(gòu)造函數(shù),產(chǎn)生了兩份父類實例,多消耗了一點內(nèi)存。

第四種. 循環(huán)拷貝繼承

?function Sub(name,age) {

? ? ?var parent=new Parent(name,age);

? ? ?for(var prop in parent){

? ? ? ? ?Sub.prototype[prop]=parent[prop];

? ? ?}

?}

?var? sub=new Sub('小紅',12);

?console.log(sub instanceof Sub); true;

?console.log(sub instanceof Parent);false;

// 優(yōu)點:

?可以繼承多個父類;

可以將父類的所有屬性和方法均繼承下來;

// 缺點:

?效率較低;

?實例不屬于父類的實例。

//第五種:循環(huán)拷貝+構(gòu)造函數(shù)

?function Sub(name,age) {

? ? Parent.call(this,name,age);

?}

?for(var prop in Parent.prototype){

? ? ?Sub.prototype[prop]=Parent.prototype[prop];

?}

?var? sub=new Sub('小紅',12);

console.log(sub instanceof Sub); true;

?console.log(sub instanceof Parent);false;

// 優(yōu)點:

?可以繼承多個父類;

可以將父類的所有屬性和方法均繼承下來;

// 缺點:

?效率較低;

實例不屬于父類的實例

第六種:共享原型

?function Sub(name,age) {

?Parent.call(this,name,age);

? ?this.name=name;

? ? ?this.age=age;

?}

?Sub.prototype=Parent.prototype;

var? sub=new Sub('小明',11);

?console.log(sub instanceof Sub); true;

?console.log(sub instanceof Parent);true;

// 優(yōu)點:

最簡單的繼承方式之一;

// 缺點:

只能繼承父類原型屬性方法,不能繼承父類構(gòu)造函數(shù)的屬性方法;//可以使用構(gòu)造函數(shù)繼承,解決這個問題

?子類共享原型上的引用屬性

第七種:圣杯模式

?function Sub(name,age){

? ? ?Parent.call(this,name,age);

?}

?function inherit(sub,parent){

? ? ?function Temp(){}

? ? ?Temp.prototype=parent.prototype;

? ? ?sub.prototype=new Temp();

? ? ?sub.prototype.constructor=Parent;

? ? ?sub.prototype.uber=Parent;

?}

?inherit(Sub,Parent);

?var? sub=new Sub('小明',11);

?console.log(sub instanceof Sub); true;

?console.log(sub instanceof Parent);true;

// 優(yōu)點:

?堪稱完美;

// 缺點:

?實現(xiàn)復(fù)雜;

不能實現(xiàn)多繼承。

// 總結(jié):

?繼承實現(xiàn)方法很多,最好的繼承方式是圣杯模式的繼承和js循環(huán)拷貝兩種,需要注意的是圣杯模式繼承不能實現(xiàn)繼承多個父類,只有循環(huán)拷貝繼承才可以很完美的實現(xiàn)繼承多個父類。

//ES6三種繼承模式

?AttackPlane.prototype.__proto__=Plan.prototype;//慎用

?AttackPlane.prototype=Object.create(Plane.prototype,function(){

? ? ?constructor:AttackPlane;//修改構(gòu)造函數(shù)

?})

?Object.setPrototypeOf(AttackPlane.prototype,Plane.prototype);//ES6,推薦

?著作權(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)容