js基礎(chǔ)回顧-繼承

腦子:我感覺我會了
手:你會個雞

方便查看风范,先上全圖


繼承復(fù)習圖

一、原型鏈繼承

//父類
function a(name){
  this.name = name
  this.colors = ['red', 'green']
}
a.prototype.say = function(){
  console.log(`姓名:${this.name}`)
}

//子類
function b(age){
  this.age = age
}
//繼承父類
//父類的參數(shù)只能在此處傳遞沪么,而不能在子類實例化時傳遞
b.prototype = new a('張三')
//添加方法硼婿,不會影響到父類
//但是添加方法必須在new a之后,如果在之前添加會被覆蓋
b.prototype.speak = function(){
  console.log(`姓名:${this.name},年齡:${this.age}`)
}
let obj1 = new b(18)

obj1.say() //姓名:張三
obj1.speak() //姓名:張三,年齡:18

obj1.colors.push('yellow')

let obj2 = new b(24)
console.log(obj2.colors) //[ 'red', 'green', 'yellow' ]

優(yōu)點:
1.既簡單又方便禽车。
2.在子類原型上添加方法不會影響到父類寇漫。
3.子類實例可以使用instanceofisPrototypeOf()識別自己的父類
console.log(a.prototype.isPrototypeOf(obj1)) //true
console.log(obj1 instanceof a) //true
缺點:
1.必須在new a之后刊殉,如果在之前添加會被覆蓋(問題不大)
2.無法實現(xiàn)多繼承,b.prototype只能指向一個對象(用得不多)
3.子類的原型上如果有引用類型數(shù)據(jù)州胳,如{}或[]记焊,
那么子類在操作這些值時會影響到原型(一般只會在原型上定義方法)
4.無法傳遞參數(shù)(很多時候會需要在子類實例化時向父類的構(gòu)造函數(shù)中傳遞參數(shù),而不是在b.prototype = new a('張三')時)

二栓撞、借用構(gòu)造函數(shù)繼承

//父類a1
function a1(name){
  this.name = name
  this.colors = ['red', 'green']
}
//父類a2
function a2(age){
  this.age = age
}
a1.prototype.a1_say = function(){
  console.log(`姓名:${this.name}`)
}
a2.prototype.a2_say = function(){
  console.log(`年齡:${this.age}`)
}

//子類
function b(name, age){
  //可以實現(xiàn)多繼承了
  a1.call(this, name)
  a2.apply(this, [age])
}
b.prototype.speak = function(){
  console.log(`姓名:${this.name},年齡:${this.age}`)
}

let obj1 = new b('張三', 18)
obj1.speak() // 姓名:張三,年齡:18

//無法繼承父類的原型方法
//obj1.a1_say() 報錯遍膜,沒有這個方法
//obj1.a2_say() 報錯,沒有這個方法

obj1.colors.push('yellow')

let obj2 = new b('李四', 24)
console.log(obj2.colors) //[ 'red', 'green' ],沒影響

優(yōu)點:
1.可以實現(xiàn)多繼承瓤湘。
2.子類在實例化父類時瓢颅,得到的都是父類獨立的屬性,多個子類互不影響弛说。
3.可以傳遞參數(shù)挽懦。
缺點:
1.看著不像是繼承,像是投機取巧木人,因為子類實例
不可以使用instanceofisPrototypeOf()識別自己的父類信柿。
2.父類的原型方法利用不到
3.構(gòu)造函數(shù)本身的缺陷造成的副作用-無法復(fù)用

這個無法復(fù)用不要迷糊,比如這一條:
//obj1.a1_say() 報錯虎囚,沒有這個方法
如果想要讓obj1擁有a1_say()角塑,那么就需要改寫父類a1

//改寫后父類a1
function a1(name){
  this.name = name
  this.colors = ['red', 'green']
  this.a1_say = function(){
    console.log(`姓名:${this.name}`)
  }
}

這么一來婆翔,子類b的實例obj1就能擁有a1_say(),但是這個方法是獨立的结胀,
如果b在new幾個實例obj2,obj3,....都會擁有獨立的a1_say()方法倦逐,浪費內(nèi)存
所以3說的無法復(fù)用指的是這葡盗。

三挡毅、組合繼承 (也叫偽經(jīng)典繼承鹰贵,=原型鏈繼承 + 借用構(gòu)造函數(shù)繼承)

//父類a1
function a1(name){
  this.name = name
}
//父類a2
function a2(age){
  this.age = age
}
a1.prototype.a1_say = function(){
  console.log(`姓名:${this.name}`)
}
a2.prototype.a2_say = function(){
  console.log(`年齡:${this.age}`)
}

//子類
function b(name, age){
  //可以實現(xiàn)多繼承
  a1.call(this, name)
  a2.apply(this, [age])
}
//但是依然只能指向一個父類
b.prototype = new a1()
//手動重定向constructor寓辱,
//并設(shè)置成不可枚舉不可刪除不可改變
Object.defineProperty(b.prototype, 'constructor', {
  value: b
})
b.prototype.speak = function(){
  console.log(`姓名:${this.name},年齡:${this.age}`)
}

let obj = new b('張三', 18)

obj.a1_say() // 姓名:張三
obj.speak()  // 姓名:張三,年齡:18
//obj.a2_say() // 報錯腋粥,沒有這個方法
看一下obj的全部細節(jié)

優(yōu)點:
他集合了原型鏈繼承借用構(gòu)造函數(shù)繼承的全部優(yōu)點蝗岖。
缺點:
1.在實現(xiàn)多繼承時侥猩,子類的原型依然只能指向一個父類的實例,也就意味著子類只能繼承一個父類的原型抵赢。
2.整個過程中欺劳,父類a1的構(gòu)造函數(shù)執(zhí)行了2次,一次是在 a1.call(this, name)铅鲤,一次是在b.prototype = new a1()划提,浪費執(zhí)行時間
3.由于條件2的作用,子類b的實例和原型都存在獨立的父類a1的構(gòu)造函數(shù)屬性name邢享,只不過原型上的屬性值為undifined鹏往,由于屬性訪問的同名屏蔽規(guī)則,你永遠也訪問不到實例的原型上的屬性name骇塘,但這確實是資源的一種浪費伊履。

四韩容、原型式繼承(注意,不是原型鏈)

//如果我們想創(chuàng)建一個繼承自普通對象的對象時唐瀑,需要以下方法
let a = {
  say: function(){
    console.log(`姓名:${this.name},年齡:${this.age}`)
  }
}

function getObject(o) {
  function F() { }
  F.prototype = o;
  return new F();
}

let b = getObject(a)

//等價于(需要支持ES5)
//let b = Object.create(a)

//也等價于(需要支持ES5)
//let b = {}
//b.__proto__ = a

優(yōu)點:
1.不用興師動眾的創(chuàng)建一個構(gòu)造函數(shù)群凶,寫起來更簡潔,也更易讀介褥。
2.可以使用isPrototypeOf()識別自己的父類
console.log(a.isPrototypeOf(b)) // true
缺點:
1.看著也不像是繼承座掘,像是工廠模式創(chuàng)建對象递惋。
2.不可以使用instanceof識別自己的父類柔滔,以為它不是一個函數(shù)
3.不能設(shè)置constructor,因為指向誰都說不通萍虽。
4.看如下代碼情況

let a = {
  say: function () {
    console.log(`姓名:${this.name},年齡:${this.age}`)
  }
}
let b = {
  name: '張三',
  age: 18
}
//如果b想繼承a睛廊,那么b就不能直接通過getObject(a)繼承,
//而是需要額外的墊片杉编,
b = Object.assign(getObject(a), b) //(需要支持ES5)
//或者使用for...in
let c = getObject(a)
for(let key in b){
  c[key] = b[key]
}
b = c

五超全、寄生式繼承(原型式繼承升級版)

function createAnother(original) {
  var clone = getObject(original); //通過調(diào)用函數(shù)創(chuàng)建一個新對象
  clone.sayHi = function () { //以某種方式來增強這個對象
    alert("hi");
  };
  return clone; //返回這個對象
}

實際上這個寄生式繼承就是在原型式繼承的基礎(chǔ)上增加了自定義屬性的過程,貌似解決了原型式繼承的缺點4邓馒,但是不靈活嘶朱,很死板,使用場景會更局限

六光酣、寄生組合式繼承(經(jīng)典繼承疏遏,=組合繼承 + 寄生式繼承 )

//原型式繼承
function getObject(o) {
  function F() { }
  F.prototype = o;
  return new F();
}
//寄生式繼承
function createAnother(b, a){
  var prototype = getObject(a.prototype); //創(chuàng)建對象
  Object.defineProperty(prototype, 'constructor', {
    value: b
  })//增強對象
  //原型鏈繼承
  b.prototype = prototype; //指定對象
}

//父類
function a(name){
  this.name = name
}
a.prototype.say = function(){
  console.log(`姓名:${this.name}`)
}

//子類
function b(name, age){
  //借用構(gòu)造函數(shù)繼承
  a.call(this, name)
  this.age = age
}

createAnother(b, a)

b.prototype.speak = function(){
  console.log(`姓名:${this.name},年齡:${this.age}`)
}

let obj = new b('張三', 18)

obj.say() // 姓名:張三
obj.speak()  // 姓名:張三,年齡:18
console.log(obj)

優(yōu)點:
可以把此圖和組合繼承做一下對比,基本上就是利用寄生式繼承彌補了組合繼承的不足救军。
缺點:
在實現(xiàn)多繼承時财异,子類的原型依然只能指向一個父類的實例,也就意味著子類只能繼承一個父類的原型唱遭。
但是多繼承用的很少戳寸,就當它是完美繼承就好了,男人何苦難為男人拷泽。

寄生組合式繼承是最終解決辦法疫鹊,所以叫經(jīng)典繼承或者完美繼承應(yīng)該不過分。

------------------------------- 分割線 -------------------------------

*其他

再談constructor
先認識兩個東西

1. 閉環(huán)
在設(shè)計產(chǎn)品原型的時候司致,多數(shù)人都會考慮一個“閉環(huán)”的概念拆吆,閉環(huán)是啥,就是畫一個圓蚌吸。


畫圓時锈拨,無論你的初始點在哪里,終點始終與初始點重合羹唠。

比如奕枢,你要登錄某個網(wǎng)站娄昆,發(fā)現(xiàn)密碼忘了,找回密碼就會在登錄框附近缝彬,你使用了找回密碼操作萌焰,那么操作成功后提示操作成功,自動跳轉(zhuǎn)登錄頁面谷浅,這就是一個小閉環(huán)扒俯。
在用戶操作完某一個流程時,都會有一個按鈕引導(dǎo)你去跳轉(zhuǎn)到另一個頁面一疯,這個頁面很大概率就是此功能初始的那個頁面撼玄。
這個閉環(huán)流程是必須的嗎?當然不是墩邀,只不過是提升體驗或者完善體系掌猛。

2. js既是一門語言,也是一款產(chǎn)品
我們前端根據(jù)產(chǎn)品的原型眉睹,使用js去生產(chǎn)一個web網(wǎng)頁荔茬,使用我們網(wǎng)頁的人我們稱之為用戶。
js這門語言本身也是一款產(chǎn)品竹海,他的生產(chǎn)者就是js的作者慕蔚,那么使用js的人(前端開發(fā))被js的作者稱為用戶。

這兩個報錯有區(qū)別嗎斋配?

站在生產(chǎn)者和用戶的角度沒有區(qū)別孔飒。
登錄報錯是 web生產(chǎn)者對于web用戶的錯誤提示。
控制臺報錯是js語言生產(chǎn)者對于js語言用戶的錯誤提示许起。

說回constructor十偶,這個屬性就是js作者針對js語言做的一個小的邏輯閉環(huán)。
這個閉環(huán)幫助js語言用戶园细,可以根據(jù)實例化對象的constructor追溯到生產(chǎn)此實例的構(gòu)造函數(shù)【雖然追溯方法還有instanceofisPrototypeOf()惦积,但constructor可以使我們在控制臺可以直觀感受】,構(gòu)造函數(shù)可以實例化對象猛频,對象還是擁有constructor狮崩,如此往復(fù),實現(xiàn)一個完善的體系鹿寻。
constructor這個閉環(huán)是必須的嗎睦柴?當然不是,如果是必須的也就不會有那么多人懷疑它存在的意義了毡熏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坦敌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌狱窘,老刑警劉巖杜顺,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蘸炸,居然都是意外死亡躬络,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門搭儒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來穷当,“玉大人,你說我怎么就攤上這事淹禾∧俨耍” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵稀拐,是天一觀的道長火邓。 經(jīng)常有香客問我丹弱,道長德撬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任躲胳,我火速辦了婚禮蜓洪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坯苹。我一直安慰自己隆檀,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布粹湃。 她就那樣靜靜地躺著恐仑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪为鳄。 梳的紋絲不亂的頭發(fā)上裳仆,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音孤钦,去河邊找鬼歧斟。 笑死,一個胖子當著我的面吹牛偏形,可吹牛的內(nèi)容都是我干的静袖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼俊扭,長吁一口氣:“原來是場噩夢啊……” “哼队橙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤捐康,失蹤者是張志新(化名)和其女友劉穎畅姊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吹由,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡若未,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了倾鲫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粗合。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖乌昔,靈堂內(nèi)的尸體忽然破棺而出隙疚,到底是詐尸還是另有隱情,我是刑警寧澤磕道,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布供屉,位于F島的核電站,受9級特大地震影響溺蕉,放射性物質(zhì)發(fā)生泄漏伶丐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一疯特、第九天 我趴在偏房一處隱蔽的房頂上張望哗魂。 院中可真熱鬧,春花似錦漓雅、人聲如沸录别。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽组题。三九已至,卻和暖如春抱冷,著一層夾襖步出監(jiān)牢的瞬間崔列,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工徘层, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留峻呕,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓趣效,卻偏偏與公主長得像瘦癌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子跷敬,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353