JS繼承

繼承是為了子類可以使用父類的所有功能汰蓉,并且能對這些功能進行擴展染服。

1. 構造函數(shù)繼承(call&apply)

說明:直接利用call或者apply方法將父類構造函數(shù)的this綁定為子類構造函數(shù)的this就可以讼昆;
缺點:無法繼承原型鏈上的屬性與方法儿惫;

function Parent1() {
  this.name = 'parent1'
}
Parent1.prototype.say = function () {
    console.log(this.name)
}
function Child1() {
  Parent1.call(this)  //構造函數(shù)繼承核心代碼
  this.type = 'child1'
}
let child1_1 = new Child1()

console.log(child1_1.name) // parent1
console.log(child1_1.say()) // child1_1.say is not a function
image

2. 原型繼承

說明:將子類的原型掛載到父類上陡叠;
缺點:子類new出來的實例,父類的屬性沒有隔離籽御,會相互影響练慕;

function Parent2() {
  this.name = 'parent2'
  this.arr = [1, 2, 3]
}
Parent2.prototype.say = function () {
    console.log(this.name)
}
function Child2() {
  this.type = 'child2'
}
Child2.prototype = new Parent2() //原型繼承核心代碼
let child2_1 = new Child2()
let child2_2 = new Child2()

console.log(child2_1.name) // parent2
console.log(child2_1.say()) // parent2
child2_1.arr.push(4)
console.log(child2_1.arr, child2_2.arr) // [1, 2, 3, 4]  [1, 2, 3, 4]
image

3. 組合繼承

說明:組合上面的構造函數(shù)與原型繼承的功能;
缺點:call()方法已經(jīng)拿到父類所有的屬性 技掏,后面再使用原型時也會有父類所有屬性铃将;

function Parent3() {
  this.name = 'parent3'
  this.arr = [1, 2, 3]
}
Parent3.prototype.say = function () {
    console.log(this.name)
}
function Child3() {
  Parent3.call(this)
  this.type = 'child3'
}
Child3.prototype = new Parent3()

let child3_1 = new Child3()
let child3_2 = new Child3()

child3_1.arr.push(4)
console.log(child3_1.arr, child3_2.arr) //  [1, 2, 3, 4]  [1, 2, 3]
// 缺點是 Parent3執(zhí)行了兩次,child3中有重復屬性
image

4. 寄生組合繼承

說明:解決組合繼承重復屬性的問題,直接將子類的原型等于父類的原型哑梳,或者是用Object.create繼承原型但不執(zhí)行父類構造函數(shù)劲阎;
注意處理子類實例的 constructor 指向問題,new Parent2()也有這個問題鸠真;

function Parent4() {
  this.name = 'parent4'
  this.arr = [1, 2, 3]
}
Parent4.prototype.say = function () {
    console.log(this.name)
}
function Child4() {
  Parent4.call(this)
  this.type = 'child4'
}

//子類的原型等于父類的原型
Child4.prototype = Parent4.prototype  
//或 Child4.prototype = Object.create(Parent4.prototype)
//修復重寫子類原型導致子類constructor屬性被修改
Child4.prototype.constructor = Child4

let child4_1 = new Child4()
let child4_2 = new Child4()
child4_1.arr.push(4)
console.log(child4_1.arr, child4_2.arr) // [1, 2, 3, 4]  [1, 2, 3]
console.log(child4_1.constructor === Child4) // true 
console.log(child4_1.constructor === Parent4)// false

// 這里的Child4就是一個繼承自Function的函數(shù)對象
console.log(Child4.constructor === Parent4) // false
image

5. Class繼承

說明:ES6新增悯仙,class是一個語法糖,就是基于寄生組合繼承來實現(xiàn)的吠卷;

class Parent5{
    constructor(){
    this.name = 'Parent5'
    this.arr = [1, 2, 3]
  }
  say(){
    console.log(this.name)
  }
}
class Child5 extends Parent5{
   constructor(){
    super() //通過super()調(diào)用父類構造函數(shù)
    this.type="Child5"
  }
}
let child5_1 = new Child5()
let child5_2 = new Child5()
child5_1.arr.push(4)
console.log(child5_1.say()) // Parent5
console.log(child5_1.arr, child5_2.arr) // [1, 2, 3, 4]  [1, 2, 3]
console.log(child5_1.constructor === Child5) // true 
console.log(child5_2.constructor === Parent5) // false
image

1.ES6里Class的Extends繼承原理
寄生組合式繼承原理:
1.使用借用構造函數(shù)(call)來繼承父類this聲明的屬性/方法
2.通過寄生式封裝函數(shù)設置父類prototype為子類prototype的原型來繼承父類的prototype聲明的屬性/方法

  1. 《你不知道的JS》上卷 A.1
    class 很好地偽裝成 JavaScript 中類和繼承設計模式的解決方案锡垄,但是它實際上起到了反作用:它隱藏了許多問題并且?guī)砹烁喔毿〉俏kU的問題。

補充:constructor的作用

constructor屬性不影響任何JavaScript的內(nèi)部屬性祭隔。instanceof檢測對象的原型鏈货岭,通常你是無法修改的(不過某些引擎通過私有的proto屬性暴露出來)。
constructor其實沒有什么用處疾渴,只是JavaScript語言設計的歷史遺留物千贯。由于constructor屬性是可以變更的,所以未必真的指向?qū)ο蟮臉嬙旌瘮?shù)程奠,只是一個提示丈牢。不過,從編程習慣上瞄沙,我們應該盡量讓對象的constructor指向其構造函數(shù)己沛,以維持這個慣例。
作者:賀師俊
鏈接:https://www.zhihu.com/question/19951896/answer/13457869

補充:new與Object.create()區(qū)別

  • new創(chuàng)建一個對象距境,執(zhí)行構造函數(shù)申尼。
  • Object.create相當于創(chuàng)建一個對象,但是不執(zhí)行構造函數(shù)垫桂。
function Parent(){
    this.name="Parent"
}
Parent.prototype.age = '18'
let child_new = new Parent()
let child_create = Object.create(Parent.prototype)

console.log(child_new instanceof Parent) // true
console.log(child_create instanceof Parent) // true
console.log(child_new.name,child_new.age) // Parent 18
console.log(child_create.name,child_create.age) // undefined "18"

//簡單模擬下 Object.create 如下:
function create(obj) {
  let F = function () {}
  F.prototype = obj
  return new F()
}
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市霹粥,隨后出現(xiàn)的幾起案子灭将,更是在濱河造成了極大的恐慌,老刑警劉巖后控,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庙曙,死亡現(xiàn)場離奇詭異,居然都是意外死亡浩淘,警方通過查閱死者的電腦和手機捌朴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來张抄,“玉大人砂蔽,你說我怎么就攤上這事∈鸸撸” “怎么了左驾?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長泽台。 經(jīng)常有香客問我什荣,道長,這世上最難降的妖魔是什么怀酷? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任稻爬,我火速辦了婚禮,結果婚禮上蜕依,老公的妹妹穿的比我還像新娘桅锄。我一直安慰自己,他們只是感情好样眠,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布友瘤。 她就那樣靜靜地躺著,像睡著了一般檐束。 火紅的嫁衣襯著肌膚如雪辫秧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天被丧,我揣著相機與錄音盟戏,去河邊找鬼。 笑死甥桂,一個胖子當著我的面吹牛柿究,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播黄选,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蝇摸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起貌夕,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤律歼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蜂嗽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苗膝,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡殃恒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年植旧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片离唐。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡病附,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出亥鬓,到底是詐尸還是另有隱情完沪,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布嵌戈,位于F島的核電站覆积,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏熟呛。R本人自食惡果不足惜宽档,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望庵朝。 院中可真熱鬧吗冤,春花似錦、人聲如沸九府。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侄旬。三九已至肺蔚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間儡羔,已是汗流浹背宣羊。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留笔链,地道東北人段只。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像鉴扫,于是被迫代替她去往敵國和親赞枕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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