深入理解JS面向?qū)ο?- JavaScript實(shí)現(xiàn)繼承的五種方式與優(yōu)缺點(diǎn)

一、類與實(shí)例

1. 類的聲明

  1. 傳統(tǒng)function類的聲明
function Animal() {
  this.name = 'name';
}
  1. ES6中的class聲明
class Animal2 {
  //構(gòu)造函數(shù)
  constructor (){
    this.name = name;
  }
}
1.1 ES6 class與ES5 function的區(qū)別:

Class的特點(diǎn):
Class在語法上更加貼合面向?qū)ο蟮膶懛?br> Class實(shí)現(xiàn)繼承更加易讀俺孙,更加容易理解
更易于寫Java等后端語言的使用
本質(zhì)還是是語法糖,使用prototype

  1. 重復(fù)定義
  • function會覆蓋之前定義的方法
  • class會報(bào)錯
  1. 構(gòu)造器 constructor
  • 在function定義的構(gòu)造函數(shù)中疏橄,其prototype.constructor屬性指向構(gòu)造器自身
  • 在class定義的類中负饲,constructor也相當(dāng)于定義在prototype屬性上
  1. 原型或者類中方法的枚舉
  • class中定義的方法不可用Object.keys(Point.prototype)枚舉到
  • function構(gòu)造器原型方法可被Object.keys(Point.prototype)枚舉到呼股,除了constructor
  • 所有原型方法屬性都可用Object.getOwnPropertyNames(Point.prototype)訪問到
  • 不管是class還是functionconstructor屬性默認(rèn)不可枚舉

2. 生成實(shí)例

如何通過類實(shí)例類的對象

  console.log(new Animal(), new Animal2());

注:如果構(gòu)造函數(shù)沒有聲明的話晨川,new函數(shù)名后面的括號可以省略

二证九、類與繼承

2.1 如何實(shí)現(xiàn)繼承

2.2 繼承的幾種方式

  1. 借助構(gòu)造函數(shù)實(shí)現(xiàn)繼承
    原理:在子類的函數(shù)體內(nèi)執(zhí)行父類,用call和apply都可以改變函數(shù)運(yùn)行的上下文共虑,導(dǎo)致父類執(zhí)行的實(shí)例都會掛載到子類上面愧怜。
function Parent1 () {
  this.name = 'parent1';
}
Parent1.prototype.say = function () {};/*new Child1().say() 報(bào)錯*/
function Child1 () {
  Parent1.call(this);/*apply也可以改變函數(shù)運(yùn)行的上下文*/
  this.type = 'child1';
}

控制臺輸出:

console.log(new Child1);

缺點(diǎn):構(gòu)造函數(shù)除了函數(shù)體里面的內(nèi)容,還可能有原型鏈上的妈拌,但是這種方式中構(gòu)造函數(shù)原型鏈上的東西并沒有被繼承拥坛。
擴(kuò)展學(xué)習(xí):javascript中apply、call和bind方法的區(qū)別

  1. 借助原型鏈實(shí)現(xiàn)繼承(彌補(bǔ)構(gòu)造函數(shù)繼承不足)
function Parent2() {
    this.name = 'parent2';
    this.play = [1, 2, 3];
}

function Child2() {
    this.type = 'child2';
}
Child2.prototype = new Parent2();
//缺點(diǎn)
console.log(new Child2());
var o1 = new Child2();
var o2 = new Child2();
console.log(o1.play, o2.play);//都為1,2,3

o1.play.push(4);//將o1重新復(fù)制

console.log(o1.play, o2.play);//都為1,2,3,4

實(shí)現(xiàn)原理:低級構(gòu)造函數(shù)的原型是高級構(gòu)造函數(shù)的實(shí)例尘分,new Child2().__proto__就是Parent2父類的一個實(shí)例對象猜惋。即new Child2().__proto__ === Parent2.prototypetruenew Child2().__proto__.name的值為parent2培愁。
缺點(diǎn):因?yàn)樵玩溨械脑褪?strong>共用的著摔,所以兩個對象不隔離。改變一個影響另一個定续。o1.__proto__ = o2.__proto__谍咆。

  1. 組合繼承方式(構(gòu)造函數(shù)+原型鏈)
function Parent3() {
    this.name = 'Parent3';
    this.play = [1, 2, 3];
}

function Child3() {
    Parent3.call(this);
    this.type = 'Child3';
}
Child3.prototype = new Parent3();
//檢驗(yàn)
console.log(new Child3());
var o1 = new Child3();
var o2 = new Child3();

o1.play.push(4);
console.log(o1.play, o2.play);//這時候結(jié)果就不一樣了 分別是 [1,2,3,4] [1,2,3]

缺點(diǎn):實(shí)例化子類的時候父類構(gòu)造函數(shù)執(zhí)行兩次。是沒有必要的私股。

  1. 組合繼承優(yōu)化一
function Parent4() {
    this.name = 'Parent4';
    this.play = [1, 2, 3];
}

function Child4() {
    Parent4.call(this);
    this.type = 'Child4';
}
Child4.prototype = Parent4.prototype;
console.log(new Child4());
var o1 = new Child4();
var o2 = new Child4();

o1.play.push(4);
console.log(o1.play, o2.play);
console.log(o1 instanceof Child4, s5 instanceof Parent4);//true, true
console.log(o1.constructor);

怎么區(qū)分摹察,是否是直接實(shí)例化的?
直接拿的父類實(shí)例

  1. 組合繼承優(yōu)化二
function Parent5() {
    this.name = 'Parent5';
    this.play = [1, 2, 3];
}

function Child5() {
    Parent5.call(this);
    this.type = 'Child5';
}
Child5.prototype = Object.create(Parent5.prototype);

創(chuàng)建中間對象倡鲸,完美~

2.3 Class和普通構(gòu)造函數(shù)實(shí)現(xiàn)繼承對比

Class實(shí)現(xiàn)(ES6)
class Animal {
    constructor(name) {
        this.name = name
    }
    eat() {
        console.log(`${this.name} eat`)
    }
}

class Dog extends Animal {
    constructor(name) {
        super(name)
        this.name = name
    }
    say() {
        console.log(`${this.name} say`)
    }
}
const dog = new Dog('husky')
dog.say()
dog.eat()
普通構(gòu)造函數(shù)實(shí)現(xiàn)
function Animal() {
    this.eat = function () {
        alert('Animal eat')
    }

}

function Dog() {
    this.bark = function () {
        alert('Dog bark')
    }
}

Dog.prototype = new Animal()
var husky = new Dog()

husky.bark()
husky.eat()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末供嚎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子峭状,更是在濱河造成了極大的恐慌克滴,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宁炫,死亡現(xiàn)場離奇詭異偿曙,居然都是意外死亡氮凝,警方通過查閱死者的電腦和手機(jī)羔巢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人竿秆,你說我怎么就攤上這事启摄。” “怎么了幽钢?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵歉备,是天一觀的道長。 經(jīng)常有香客問我匪燕,道長蕾羊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任帽驯,我火速辦了婚禮龟再,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尼变。我一直安慰自己利凑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布嫌术。 她就那樣靜靜地躺著哀澈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪度气。 梳的紋絲不亂的頭發(fā)上割按,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音蚯嫌,去河邊找鬼哲虾。 笑死,一個胖子當(dāng)著我的面吹牛择示,可吹牛的內(nèi)容都是我干的束凑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼栅盲,長吁一口氣:“原來是場噩夢啊……” “哼汪诉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谈秫,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤扒寄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拟烫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體该编,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年硕淑,在試婚紗的時候發(fā)現(xiàn)自己被綠了课竣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘉赎。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖于樟,靈堂內(nèi)的尸體忽然破棺而出公条,到底是詐尸還是另有隱情,我是刑警寧澤迂曲,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布靶橱,位于F島的核電站,受9級特大地震影響路捧,放射性物質(zhì)發(fā)生泄漏关霸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一杰扫、第九天 我趴在偏房一處隱蔽的房頂上張望谒拴。 院中可真熱鬧,春花似錦涉波、人聲如沸英上。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苍日。三九已至,卻和暖如春窗声,著一層夾襖步出監(jiān)牢的瞬間相恃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工笨觅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拦耐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓见剩,卻偏偏與公主長得像杀糯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子苍苞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容