一張圖理解prototype、proto和constructor的三角關(guān)系

前面的話

javascript里的關(guān)系又多又亂伯病。作用域鏈?zhǔn)且环N單向的鏈?zhǔn)疥P(guān)系造烁,還算簡(jiǎn)單清晰;this機(jī)制的調(diào)用關(guān)系午笛,稍微有些復(fù)雜惭蟋;而關(guān)于原型,則是prototype药磺、proto和constructor的三角關(guān)系告组。本文先用一張圖開(kāi)宗明義,然后詳細(xì)解釋原型的三角關(guān)系

圖示

proto

概念

上圖中的復(fù)雜關(guān)系癌佩,實(shí)際上來(lái)源就兩行代碼

function Foo(){}; var f1 = new Foo;

【構(gòu)造函數(shù)】

用來(lái)初始化新創(chuàng)建的對(duì)象的函數(shù)是構(gòu)造函數(shù)木缝。在例子中,F(xiàn)oo()函數(shù)是構(gòu)造函數(shù)

【實(shí)例對(duì)象】

通過(guò)構(gòu)造函數(shù)的new操作創(chuàng)建的對(duì)象是實(shí)例對(duì)象驼卖“奔。可以用一個(gè)構(gòu)造函數(shù),構(gòu)造多個(gè)實(shí)例對(duì)象

function Foo(){}; var f1 = new Foo; var f2 = new Foo;
console.log(f1 === f2);//false

【原型對(duì)象及prototype】

構(gòu)造函數(shù)有一個(gè)prototype屬性酌畜,指向?qū)嵗龑?duì)象的原型對(duì)象怎囚。通過(guò)同一個(gè)構(gòu)造函數(shù)實(shí)例化的多個(gè)對(duì)象具有相同的原型對(duì)象。經(jīng)常使用原型對(duì)象來(lái)實(shí)現(xiàn)繼承

function Foo(){};
Foo.prototype.a = 1;
var f1 = new Foo;
var f2 = new Foo;

console.log(Foo.prototype.a);//1
console.log(f1.a);//1
console.log(f2.a);//1

【constructor】

原型對(duì)象有一個(gè)constructor屬性桥胞,指向該原型對(duì)象對(duì)應(yīng)的構(gòu)造函數(shù)

function Foo(){};
console.log(Foo.prototype.constructor === Foo);//true

由于實(shí)例對(duì)象可以繼承原型對(duì)象的屬性恳守,所以實(shí)例對(duì)象也擁有constructor屬性,同樣指向原型對(duì)象對(duì)應(yīng)的構(gòu)造函數(shù)

function Foo(){}; var f1 = new Foo;
console.log(f1.constructor === Foo);//true

【proto】

實(shí)例對(duì)象有一個(gè)proto屬性贩虾,指向該實(shí)例對(duì)象對(duì)應(yīng)的原型對(duì)象

function Foo(){}; var f1 = new Foo;
console.log(f1.__proto__ === Foo.prototype);//true<

說(shuō)明

概念介紹完了催烘,現(xiàn)在對(duì)圖示的關(guān)系進(jìn)行詳細(xì)說(shuō)明

function Foo(){}; var f1 = new Foo;

【第一部分: Foo】

image

實(shí)例對(duì)象f1是通過(guò)構(gòu)造函數(shù)Foo()的new操作創(chuàng)建的。構(gòu)造函數(shù)Foo()的原型對(duì)象是Foo.prototype缎罢;實(shí)例對(duì)象f1通過(guò)proto屬性也指向原型對(duì)象Foo.prototype

function Foo(){}; var f1 = new Foo;
console.log(f1.__proto === Foo.prototype);//true

實(shí)例對(duì)象f1本身并沒(méi)有constructor屬性伊群,但它可以繼承原型對(duì)象Foo.prototype的constructor屬性

function Foo(){}; var f1 = new Foo;
console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true
console.log(f1.hasOwnProperty('constructor'));//false

下圖是實(shí)例對(duì)象f1的控制臺(tái)效果

image

【第二部分: Object】

image

Foo.prototype是f1的原型對(duì)象,同時(shí)它也是實(shí)例對(duì)象策精。實(shí)際上舰始,任何對(duì)象都可以看做是通過(guò)Object()構(gòu)造函數(shù)的new操作實(shí)例化的對(duì)象

所以,F(xiàn)oo.prototype作為實(shí)例對(duì)象咽袜,它的構(gòu)造函數(shù)是Object()丸卷,原型對(duì)象是Object.prototype。相應(yīng)地询刹,構(gòu)造函數(shù)Object()的prototype屬性指向原型對(duì)象Object.prototype谜嫉;實(shí)例對(duì)象Foo.prototype的proto屬性同樣指向原型對(duì)象Object.prototype

function Foo(){}; var f1 = new Foo;
console.log(Foo.prototype.__proto__ === Object.prototype);//true

實(shí)例對(duì)象Foo.prototype本身具有constructor屬性萎坷,所以它會(huì)覆蓋繼承自原型對(duì)象Object.prototype的constructor屬性

function Foo(){}; var f1 = new Foo;
console.log(Foo.prototype.constructor === Foo);//true
console.log(Object.prototype.constructor === Object);//true
console.log(Foo.prototype.hasOwnProperty('constructor'));//true

下圖是實(shí)例對(duì)象Foo.prototype的控制臺(tái)效果

image

如果Object.prototype作為實(shí)例對(duì)象的話,其原型對(duì)象是什么沐兰,結(jié)果是null哆档。私以為,這可能也是typeof null的結(jié)果是'object'的原因之一吧

console.log(Object.prototype.__proto__ === null);//true

【第三部分: Function】

image

前面已經(jīng)介紹過(guò)僧鲁,函數(shù)也是對(duì)象虐呻,只不過(guò)是具有特殊功能的對(duì)象而已。任何函數(shù)都可以看做是通過(guò)Function()構(gòu)造函數(shù)的new操作實(shí)例化的結(jié)果

如果把函數(shù)Foo當(dāng)成實(shí)例對(duì)象的話寞秃,其構(gòu)造函數(shù)是Function()斟叼,其原型對(duì)象是Function.prototype;類似地春寿,函數(shù)Object的構(gòu)造函數(shù)也是Function()朗涩,其原型對(duì)象是Function.prototype

function Foo(){}; var f1 = new Foo;
console.log(Foo.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.prototype);//true

原型對(duì)象Function.prototype的constructor屬性指向構(gòu)造函數(shù)Function();實(shí)例對(duì)象Object和Foo本身沒(méi)有constructor屬性绑改,需要繼承原型對(duì)象Function.prototype的constructor屬性

function Foo(){}; var f1 = new Foo;
console.log(Function.prototype.constructor === Function);//true
console.log(Foo.constructor === Function);//true
console.log(Foo.hasOwnProperty('constructor'));//false
console.log(Object.constructor === Function);//true
console.log(Object.hasOwnProperty('constructor'));//false

所有的函數(shù)都可以看成是構(gòu)造函數(shù)Function()的new操作的實(shí)例化對(duì)象谢床。那么,F(xiàn)unction可以看成是調(diào)用其自身的new操作的實(shí)例化的結(jié)果

所以厘线,如果Function作為實(shí)例對(duì)象识腿,其構(gòu)造函數(shù)是Function,其原型對(duì)象是Function.prototype

console.log(Function.__proto__ === Function.prototype);//true
console.log(Function.prototype.constructor === Function);//true
console.log(Function.prototype === Function.prototype);//true

如果Function.prototype作為實(shí)例對(duì)象的話造壮,其原型對(duì)象是什么呢渡讼?和前面一樣,所有的對(duì)象都可以看成是Object()構(gòu)造函數(shù)的new操作的實(shí)例化結(jié)果耳璧。所以成箫,F(xiàn)unction.prototype的原型對(duì)象是Object.prototype,其原型函數(shù)是Object()

console.log(Function.prototype.__proto__ === Object.prototype);//true

第二部分介紹過(guò)旨枯,Object.prototype的原型對(duì)象是null

console.log(Object.prototype.__proto__ === null);//true

總結(jié)

【1】函數(shù)(Function也是函數(shù))是new Function的結(jié)果蹬昌,所以函數(shù)可以作為實(shí)例對(duì)象,其構(gòu)造函數(shù)是Function()攀隔,原型對(duì)象是Function.prototype

【2】對(duì)象(函數(shù)也是對(duì)象)是new Object的結(jié)果皂贩,所以對(duì)象可以作為實(shí)例對(duì)象,其構(gòu)造函數(shù)是Object()昆汹,原型對(duì)象是Object.prototype

【3】Object.prototype的原型對(duì)象是null

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末先紫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子筹煮,更是在濱河造成了極大的恐慌,老刑警劉巖居夹,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件败潦,死亡現(xiàn)場(chǎng)離奇詭異本冲,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)劫扒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)檬洞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人沟饥,你說(shuō)我怎么就攤上這事添怔。” “怎么了贤旷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵广料,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我幼驶,道長(zhǎng)艾杏,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任盅藻,我火速辦了婚禮购桑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘氏淑。我一直安慰自己勃蜘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布假残。 她就那樣靜靜地躺著缭贡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪守问。 梳的紋絲不亂的頭發(fā)上匀归,一...
    開(kāi)封第一講書(shū)人閱讀 51,245評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音耗帕,去河邊找鬼穆端。 笑死,一個(gè)胖子當(dāng)著我的面吹牛仿便,可吹牛的內(nèi)容都是我干的体啰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嗽仪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荒勇!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起闻坚,我...
    開(kāi)封第一講書(shū)人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沽翔,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體仅偎,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跨蟹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了橘沥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窗轩。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖座咆,靈堂內(nèi)的尸體忽然破棺而出痢艺,到底是詐尸還是另有隱情,我是刑警寧澤介陶,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布堤舒,位于F島的核電站,受9級(jí)特大地震影響斤蔓,放射性物質(zhì)發(fā)生泄漏植酥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一弦牡、第九天 我趴在偏房一處隱蔽的房頂上張望友驮。 院中可真熱鬧,春花似錦驾锰、人聲如沸卸留。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)耻瑟。三九已至,卻和暖如春赏酥,著一層夾襖步出監(jiān)牢的瞬間喳整,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工裸扶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留框都,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓呵晨,卻偏偏與公主長(zhǎng)得像魏保,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摸屠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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