JS原型鏈侈沪、__proto__和prototype

不知道你有沒有想過這樣一個(gè)問題

  • 為什么我定義一個(gè)數(shù)組,它就有push晚凿、join亭罪、pop、shift等方法歼秽,我明明什么也沒寫坝σ邸?
  • 為什么我定義一個(gè)函數(shù)哲银,它就有call扛吞、apply、length等屬性/方法荆责,我也什么都沒有做呀滥比?!
  • 為什么我定義一個(gè)對(duì)象做院,它就有toString盲泛、valueOf等方法,我更是什么都沒有做呀键耕?寺滚!

1、我們先來說說對(duì)象屈雄。

當(dāng)我們定義一個(gè)對(duì)象時(shí)

var obj = {}


我們發(fā)現(xiàn)obj下面有一個(gè)屬性名叫__proto__村视,(它是個(gè)對(duì)象)
obj.__proto__里面又有很多屬性,包括 valueOf酒奶、toString蚁孔、constructor 等。當(dāng)我們需要找obj.valueOf這個(gè)屬性時(shí)惋嚎,發(fā)現(xiàn)obj本身沒有沒有杠氢,那么它就會(huì)去查找obj.__proto__是否有這個(gè)屬性,如果還沒有另伍,它去找obj.__proto__.__proto__鼻百,直到找到這個(gè)屬性或null為止,在這個(gè)讀取屬性的過程中,是沿著__proto__組成的鏈子來搜索的温艇,這個(gè)鏈子我們稱為原型鏈因悲。
如果obj自身定義了一個(gè)valueOf屬性,那么它找到自身的valueOf之后就不再沿著__proto__來找中贝,因?yàn)橐呀?jīng)找到了囤捻,沒有必要繼續(xù)找了,也就是說

  • 新增的屬性不會(huì)沿著__proto__查找
  • 讀取屬性會(huì)沿著__proto__邻寿,直到找到這個(gè)屬性蝎土,或者是null為止。

2绣否、那么obj.__proto__到底是什么呢誊涯?

__proto__是一個(gè)簡(jiǎn)單的訪問器屬性,它總是指向它的構(gòu)造函數(shù)的prototype蒜撮。即原型對(duì)象暴构。

所有的對(duì)象都繼承了Object.prototype的屬性和方法,
它們可以被覆蓋(除了以null為原型的對(duì)象段磨,如 Object.create(null))取逾。
例如,新的構(gòu)造函數(shù)的原型覆蓋原來的構(gòu)造函數(shù)的原型苹支,提供它們自己的 toString() 方法.砾隅。對(duì)象的原型的改變會(huì)傳播到所有對(duì)象上,除非這些屬性和方法被其他對(duì)原型鏈更里層的改動(dòng)所覆蓋债蜜。

所有的對(duì)象會(huì)動(dòng)態(tài)生成一個(gè)__proto__指向它構(gòu)造函數(shù)的原型(prototype )
當(dāng)我們?nèi)ゲ檎?code>obj.valueOf這個(gè)屬性時(shí)晴埂,他會(huì)沿著原型鏈去查找obj.__proto__.valueOf,而obj.__proto__指向obj.constructor.prototype寻定。即

obj.__proto__ === obj.constructor.prototype  // true
obj.__proto__.toString=== obj.constructor.prototype.toString  // true

我們知道obj的構(gòu)造函數(shù)就是Object儒洛,那么我們也可以這么寫

obj.__proto__ === Object.prototype  // true
obj.__proto__.toString === Object.prototype.toString  // true

3、對(duì)于數(shù)組

以push方法為例狼速,我們知道當(dāng)我們定義一個(gè)空數(shù)組時(shí)琅锻,我們可以直接調(diào)用push方法,根據(jù)上面的解釋向胡,他會(huì)沿著這個(gè)數(shù)組的__proto__去查找這個(gè)方法浅浮。

var array = []
array.push === array.__proto__.push // true

array.__proto__指向它構(gòu)造函數(shù)的prototype,那么

array.__proto__.push === array.constructor.prototype.push // true
array.__proto__.push === Array.prototype.push  // true

終于找到push方法了捷枯。

問題來了,我們知道array也是對(duì)象专执,那么JS是怎么知道array也是對(duì)象的呢淮捆?

答:通過__proto__

我們先看Array.__proto__指向誰(shuí)

Array.__proto__ === Function.prototype   // true

你也許會(huì)納悶,怎么Array.__proto__指向的怎么是函數(shù)的原型對(duì)象呢?因?yàn)锳rray的構(gòu)造函數(shù)就是函數(shù)攀痊,不信你console.log(Array.constructor)試試桐腌?而函數(shù)的原型對(duì)象的__proto__最終指向Object

Function.prototype.__proto__ === Object.prototype  // true
Array.__proto__.__proto__ === Object.prototype  // true

或者我們也可以這樣寫

Array.prototype.__proto__ === Object.prototype  // true

最終歸宿都是Object。

至此我們看下一個(gè)小小的array都經(jīng)歷了什么

array.__proto__  ----> Array.prototype ----> Array.prototype.__proto__---->
Object.prototype

這樣也就不難理解為什么數(shù)組(函數(shù))也是個(gè)對(duì)象了苟径。

4案站、一切皆對(duì)象?

也許你會(huì)迷惑棘街,既然Array.__proto__.__proto__ = Object.prototype蟆盐,那么

Number.__proto__.__proto__ === Object.prototype   // true
Boolean.__proto__ .__proto__ === Object.prototype   // true
String.__proto__.__proto__ === Object.prototype   // true

為什么我們不可以說數(shù)字/布爾/字符串也是對(duì)象呢?
這要看這個(gè)數(shù)字/布爾/字符串是怎么創(chuàng)建的了遭殉。
以數(shù)字為例

var a = 1
var b = new Number(1)

我們知道基本類型是沒有屬性的石挂,即便可以訪問到這個(gè)屬性,也是訪問的臨時(shí)對(duì)象的屬性险污,訪問完就銷毀了痹愚,即使你發(fā)現(xiàn)a.__proto__.__proto__指向是Object,也是new Number指向的蛔糯,跟a沒有半毛錢關(guān)系拯腮,因?yàn)閍就是個(gè)number。
b就不一樣了蚁飒,b是構(gòu)造函數(shù)Number構(gòu)造出來的一個(gè)對(duì)象动壤,只不過他的值是1,它可是有__proto__屬性的飒箭,那么b就可以愉快的指來指去了狼电。

b.__proto__.__proto__ === Object.prototype  // true

所以a是一個(gè)number,而b是一個(gè)object弦蹂。
同理字符串和布爾也是如此肩碟。

來跟我一起大聲念JS的七種數(shù)據(jù)類型:
number , string , boolean , undefined , null , object , symbol
說JS一切皆對(duì)象的,你們當(dāng)其他類型是吃干飯的么凸椿?

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市脑漫,隨后出現(xiàn)的幾起案子髓抑,更是在濱河造成了極大的恐慌,老刑警劉巖优幸,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吨拍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡网杆,警方通過查閱死者的電腦和手機(jī)羹饰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門伊滋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人队秩,你說我怎么就攤上這事笑旺。” “怎么了馍资?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵筒主,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我鸟蟹,道長(zhǎng)乌妙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任戏锹,我火速辦了婚禮冠胯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锦针。我一直安慰自己荠察,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布奈搜。 她就那樣靜靜地躺著悉盆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪馋吗。 梳的紋絲不亂的頭發(fā)上焕盟,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音宏粤,去河邊找鬼脚翘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绍哎,可吹牛的內(nèi)容都是我干的来农。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼崇堰,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼沃于!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起海诲,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤繁莹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后特幔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咨演,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年蚯斯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雪标。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片零院。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖村刨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撰茎,我是刑警寧澤嵌牺,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站龄糊,受9級(jí)特大地震影響逆粹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炫惩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一僻弹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧他嚷,春花似錦蹋绽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至粘咖,卻和暖如春蚣抗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瓮下。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工翰铡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讽坏。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓锭魔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親震缭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赂毯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

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