js 原型鏈

什么是原型鏈?

我們先看一下下面的這個小例子:

let data = {
    name:'merit'
}
alert(data)

這時候,彈出的窗口里面顯示著 [object Object]糜工,相信大家應(yīng)該也都見過這個弊添,可是為什么會是這個呢?

其實捌木,再用alert顯示對象的時候油坝,會默認(rèn)調(diào)用對象的toString函數(shù),可是,我們明明沒有給data設(shè)置這個函數(shù)啊澈圈,那這個函數(shù)又是哪里來的呢彬檀,這時候我們就把整個data給打印一下看一看:

我們看到,data不止有我們設(shè)置的name屬性瞬女,還有一個我們沒設(shè)置的__proto__屬性窍帝,那這屬性里面又是些什么東西呢,讓我們再打開看一下:

1593426483110.png

這時候我們就在里賣弄看到了我們用到的toString函數(shù)诽偷。

上面這個是直接創(chuàng)建了一個Object實例對象坤学,下面讓我們用構(gòu)造函數(shù)創(chuàng)建一個對象,看看是什么效果:

function MyObj(name){
    this.name = name
}
MyObj.prototype.myToString = function(){
    console.log(this.name)
}
let bar = new MyObj('merit')
alert(bar)

結(jié)果顯然是和上面的一樣為 [object Object]报慕,我們來看一看這個的toString方法是怎么得到的:


我們可以看到拥峦,bar這個對象本身有一個__proto__屬性,這個屬性里面竟然還有我們通過MyObj.prototype.myToString定義的函數(shù)卖子,這個我們一會兒再說略号。然后在這個__proto__屬性中,還有一個__proto__屬性洋闽,里面有著我們所需要的toString函數(shù)玄柠。

當(dāng)我們調(diào)用對象的某個屬性的時候,就會先去看它本身有沒有這個屬性诫舅,沒有的話羽利,就會去看他的__proto__中有沒有這個屬性,有的話就調(diào)用刊懈,沒有的話就繼續(xù)看這個__proto__中的__proto__里面有沒有这弧,只到最后一層,如果都沒有的話虚汛,才會報錯匾浪。

上面這個例子中,如果把myToString函數(shù)名換成toString卷哩,那么alert(bar)再調(diào)用bar.toString就是我們自己寫的內(nèi)容了蛋辈。

這種通過__proto__屬性一層層的連接形成了一個鏈的樣子就叫做原型鏈。

prototype與_proto_的關(guān)系

當(dāng)我們創(chuàng)建一個對象的實例的時候将谊,實例本身就會自帶一個__proto__屬性冷溶,該屬性指向其構(gòu)造函數(shù)的prototype屬性,而所有構(gòu)造函數(shù)的prototype屬性都是一個Object的一個實例尊浓。而這個實例就會有一個指向Object.prototype的_proto__逞频,所有對象類型無論是Array,String還是Function,最終的__proto__指向都是這個位置栋齿。

明白了原型鏈苗胀,其實就能夠理解很多的東西了托酸,比如我們經(jīng)常使用的instanceof判斷類型和實現(xiàn)繼承的一些方式。

instanceof

我們經(jīng)常使用instanceof去判斷一個數(shù)據(jù)的數(shù)據(jù)類型柒巫,其實A instanceof B的本質(zhì)就是去判斷A這個對象的原型鏈上是否有B.prototype励堡。這樣你就能很好的明白下面的一些結(jié)果了:

let bar  = 'merit'
let bar_s = new String('merit')
let bar_a = [1,2,3]
let bar_f = function(){console.log(1)}

bar instanceof Object //false
bar_s instanceof String //true
bar_a instanceof Array//true
bar_f instanceof Function//true

//任何對象類型的原型鏈終點都指向到Object的prototype
String instanceof Object//true
Array instanceof Object//true
Function instanceof Object //true
Object instanceof Object //true

Object instanceof Function //true
String instanceof Function//true
Array instanceof Function //true
Function instanceof Function //true
//對于最后一組,我們要知道{},[]創(chuàng)建對象或數(shù)組都是new Object()/new Array()的語法糖堡掏,而Object,Array本身這些構(gòu)造器应结,又都是Function的一個實例。

既然對instanceof的原理理解了泉唁,我們也可以簡單的寫一個簡易版的instanceof

//myInstanceof
function myInstanceof(A,B){
    while(A.__proto__){
        if(A.__proto__===B.prototype){
            return true
        }
        A=A.__proto__
    }
    return false
}

繼承

通過對原型鏈的理解鹅龄,我們就可以很好的實現(xiàn)繼承了。

function Parent(value){
    this.tag='我是父對象'
    this.val = value
}
Parent.prototype.showVal = function(){console.log(this.val)}

組合繼承

function Child(value,name){
    Parent.apply(this,value) //通過這一步可以保證子對象里面有父對象的值
    this.tag = '我是子對象' //會覆蓋掉父對象的賦值
    this.name = name;
}
//接下來我們要保證子對象能調(diào)用父對象的方法
Child.prototype = new parent()
Child.prototype.constructor = Child 
let bar = new Child('111','merit')

雖然我不知道為什么這個名字叫做組合對象亭畜,但是原理還是很明顯的扮休,就是讓子對象的prototype指向父對象的一個實例,然后利用這個實例的__proto__去調(diào)用父對象的方法拴鸵,下面一張圖應(yīng)該能很詳細(xì)的說明這一點

通過上面這個圖玷坠,我們可以看出子對象的一個實例bar是如何調(diào)用父對象的方法的,但是我們也能夠看出來一個問題劲藐,就是通過這種構(gòu)建一個父對象的實例在中間進(jìn)行過渡的方式八堡,會造成內(nèi)存的浪費,因為我們并不會使用到父對象里面的值聘芜,這時候我們就可以通過下面的繼承方式來改善

寄生組合繼承

function Child(value,name){
    Parent.call(this,value)
    this.tag='子對象'
    this.name = name
}
//這個會創(chuàng)造一個__proto__指向Parent.prototype的空對象
let childPrototype = Object.creat(Parent.prototype)
childPrototype.constructor = Child
Child.prototype = childPrototype

通過創(chuàng)建父對象實例而是通過Object創(chuàng)建空對象的方式繼承兄渺,就很好的解決了上面的問題,可以說是一種比較完美的繼承方案了汰现。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末挂谍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子瞎饲,更是在濱河造成了極大的恐慌口叙,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件企软,死亡現(xiàn)場離奇詭異庐扫,居然都是意外死亡饭望,警方通過查閱死者的電腦和手機仗哨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铅辞,“玉大人厌漂,你說我怎么就攤上這事≌迳海” “怎么了苇倡?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我旨椒,道長晓褪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任综慎,我火速辦了婚禮涣仿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘示惊。我一直安慰自己好港,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布米罚。 她就那樣靜靜地躺著钧汹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪录择。 梳的紋絲不亂的頭發(fā)上拔莱,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機與錄音隘竭,去河邊找鬼辨宠。 笑死,一個胖子當(dāng)著我的面吹牛货裹,可吹牛的內(nèi)容都是我干的嗤形。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼弧圆,長吁一口氣:“原來是場噩夢啊……” “哼赋兵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起搔预,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤霹期,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拯田,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體历造,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年船庇,在試婚紗的時候發(fā)現(xiàn)自己被綠了吭产。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸭轮,死狀恐怖臣淤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情窃爷,我是刑警寧澤邑蒋,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布姓蜂,位于F島的核電站,受9級特大地震影響医吊,放射性物質(zhì)發(fā)生泄漏钱慢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一卿堂、第九天 我趴在偏房一處隱蔽的房頂上張望滩字。 院中可真熱鬧,春花似錦御吞、人聲如沸麦箍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挟裂。三九已至,卻和暖如春揍诽,著一層夾襖步出監(jiān)牢的瞬間诀蓉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工暑脆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渠啤,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓添吗,卻偏偏與公主長得像沥曹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子碟联,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351