Javascript中的原型鏈、prototype、__proto__的關系

下圖是帥華君用Illustrator制作的可視化信息圖,希望能幫你理清Javascript對象與__proto__、prototype和原型鏈之間的關系。如果暫時看不懂也沒關系,這篇文章讓你從0變成1。

帥華君使用Adobe Illustrator設計

零、感性認識JS里的“德羅斯特效應”之原型鏈

如果你打開瀏覽器的控制面板,隨便輸入一個JS內置的構造器函數,比如Array,控制臺輸出的是一個名為Array的函數體,這好像并沒有什么稀奇的,但是,當你接著輸入Array.prototype,控制面板輸出了一堆我們經常用到的Array構造器的方法,把目光轉移到最下方,有一個叫__proto__的屬性,好奇的點開,

咦~?列表列出的不是Object構造器的方法么,里邊有我們非常熟悉的hasOwnProperty還有toString等方法。我們常說的一切皆對象,一切對象皆null這么玄妙的編程界哲理和這種嵌套會不會有什么關系呢?更神奇的在下邊。

繼續深入思考,Array是構造器,那么控制臺輸出的Array.prototype的所有屬性中的constructor(翻譯:構造器)又是指向什么?點開看看,之后就像身處德羅斯特效應中一樣,__proto__和constructor,還有Array構造器中常用的方法名不斷的出現,一層套一層,一層層展開,沒有盡頭。。。

一、滿滿一堂證明題課

當你也發現了JS里這種循環往復、不斷嵌套的規律后,仍然不相信自己的眼睛,于是決定親自證明一下,哦不,是好幾下。(對于初學者只靠空想太燒腦,于是本寶寶做了幾個GIF動圖。)

1、怎么證明你就是你?

這個問題可難不倒JS中的構造器們,一個證明秒秒鐘證明“我就是我”,是顏色不一樣的煙火。

拿Array舉例,Array.prototype中有一個constructor屬性,這個屬性的值就是Array構造器自己!

2、“遺傳進化鏈__proto__”,怎么證明一切皆對象?

所有的JS內置構造器都本是對象,這要從long long ago說起??墒菑氖裁淳€索開始向過去前進呢,原型鏈(我給他起了一個名字叫遺傳進化鏈)就是突破口。所有JS構造器(當然不止構造器有)都有一個__proto__屬性,這是原型鏈指針,指向進化成它的“那個”。(就像我的__proto__指針指向我父母,我父母各自的__proto__指向他們的父母... ...鬼知道最盡頭的Ta經歷了什么???(手動黑人問號臉)。在進化的過程中,父母的遺傳物質(屬性、方法)被我的__proto__指針引用著,同時我也變異出了自己的能力(屬性、方法),然后我的子代的__proto__指針又引用我的遺傳物質。額!為毛突然莫名臉紅~)

從上圖中發現,JS內置構造器其中之一的Array原本就是一個函數,而這個函數就是Function的prototype,所以Function.prototype有的方法,JS內置構造器都有,比如call()、apply()、bind()等(其實我們自定義的函數也是繼承自Function.prototype,所以我們自己也可以定義構造器,創造屬于自己的小小王國)。(所以在編程的世界里模擬一個宇宙系統是有可能的,說不定我們本來就生活在被設定好的編程世界里哦。)

而Function.prototype的進化鏈指針又指向了Object.prototype。

3、怎么證明到頭來一切都是空?

不管你從那個屬性開始,連續引用__proto__的指針,最后輸出的那個值就是null。

上圖中,一時手殘,打成大寫的P了。

萬物都是從無生出來的?!Hi boy 老聃的道德經han莊子 讀多了吧

4、怎么證明所有JS內置構造器和自定義函數都是Function構造器的原型(prototype)。

不斷強化這一認知,實踐出真知。

①、String構造器的進化鏈指針__proto__指向Function構造器的原型

//String構造器String.__Proto__ ===Function.prototype

②、Number構造器的進化鏈指針__proto__指向Function構造器的原型

//Number構造器Number.__Proto__ ===Function.prototype

③、Boolean構造器的進化鏈指針__proto__指向Function構造器的原型

//Boolean構造器Boolean.__Proto__ ===Function.prototype

④、Array構造器的進化鏈指針__proto__指向Function構造器的原型

//Array構造器Array.__Proto__ ===Function.prototype

⑤、沒錯,Function構造器的進化鏈指針__proto__也指向自己的原型

//Function構造器Function.__Proto__ ===Function.prototype

⑥、Date構造器的進化鏈指針__proto__指向Function構造器的原型

//Date構造器Date.__Proto__ ===Function.prototype

⑦;、Error構造器的進化鏈指針__proto__指向Function構造器的原型

//Error構造器Error.__Proto__ ===Function.prototype

⑧、Object構造器的進化鏈指針__proto__指向Function構造器的原型

//Object構造器Object.__Proto__ ===Function.prototype

⑨、RegExp構造器的進化鏈指針__proto__指向Function構造器的原型

//RegExp構造器RegExp.__Proto__ ===Function.prototype

⑩、Event構造器的進化鏈指針__proto__指向Function構造器的原型

//Event構造器Event.__Proto__ ===Function.prototype

這里需要注意所有構造器的prototype都是對象(object)類型,只有Function.prototype是函數(function)類型,這是為了保證函數構造器們的__proto__指向的都是函數。

二、咦?JSON和Math哪去啦?

JS內置的構造器函數都可以使用new關鍵字實例化一個對象,我們稱實例化后的這個對象就是某某構造器的一個實例。就像我們每一個“人”都是“人類”這個構造器函數的一個實例

//實例化一個String構造函數varstr =newString("Hi, today! ");

既然上邊10個構造器函數都能這樣實例化對象,那么JSON和Math是不是也可以用new 關鍵字實例化呢?試試看!

//嘗試實例化JSON和Math兩個構造器函數varjson =newJSON();varMath=newMath();

哦No,不可以。JSON和Math不是構造器函數,他們是普通的對象。

上邊提到過,只有構造器函數才能使用new 關鍵字實例化一個對象,而JSON和Math已經是對象了,所以我們可以不用實例化直接使用JSON和Math中的屬性和方法~~(我們實例化的目就是想用實例化后的對象里的屬性和方法,那么既然JSON和Math已經是對象了,就省去實例化的操作嘍。當然,能實例化有能實例化的好處~)

所以JSON和Math不屬于10個構造器函數,但他們12個共同屬于Javascript的內置對象。

三、__proto__進化鏈指針設計為什么如此重要!

javascript中為什么會有__proto__原型鏈的設計,不防做一個小實驗先。

//實例化一個String對象varstr =newString("Hi!")

我們先實例化一個String對象并將其賦值給str這個變量,然后我們輸出這個str

從str輸出的內容來看,str有四個屬性,分別是0、1、2、length

//我們一個個輸出這些屬性console.log(str[0])//Hconsole.log(str[1])//iconsole.log(str[2])//!console.log(str['length'])//3

這毋庸置疑,但是接著往下看。

//charAt()是str對象中不存在的屬性方法,但是沒有報錯,依然可以輸出!str.charAt(0)// 輸出'H'

charAt()是str對象中不存在的屬性方法,但是沒有報錯,依然可以輸出!

這是為什么?這就是進化鏈__proto__的用處。

str這個對象本身的確沒有charAt()這個方法,但是str的進化鏈上存在這個屬性方法,那么charAt()這個方法在進化鏈的那個節點上呢?

哦~,原來String.prototype擁有charAt這個方法,而str的__proto__指針指向String.prototype

有小伙伴就問了,“那為什么我爺爺寫得一手好毛筆字,可我卻沒遺傳這一點呢?”“呵呵”

這么說的話,str.__proto__.__proto__指向的對象所擁有的屬性str也都可以直接用嘍?答案是肯定的!

看到str.__proto__.__proto__指向的對象所擁有的屬性中有一個hasOwnProperty屬性方法了么,str可以直接使用這個屬性方法。

在驗證之前先說下str.__proto__.__proto__指向了誰?指向的是Object的prototype屬性。

str.__proto__.__proto__ ===Object.prototype// true

Object.prototype.hasOwnProperty()屬性方法用來檢驗一個對象是否自己擁有一個屬性而非通過進化鏈__proto__繼承來的屬性。

好的,實驗開始:

//檢查str是否擁有length屬性str.hasOwnProperty('length')//true//檢查str是否擁有0屬性(str.charAt(0)的輸出是'H')str.hasOwnProperty(0)//true//檢查str是否擁有1屬性str.hasOwnProperty(1)//true//檢查str是否擁有2屬性str.hasOwnProperty(2)//true//檢查str是否擁有3屬性(str的length是3,所以索引值從0開始,所以索引最大是2,所以沒有3這個屬性)str.hasOwnProperty(3)//false//str是否擁有hasOwnProperty這個屬性呢?答案是否定的。str.hasOwnProperty('hasOwnProperty')//false

四、結語

現在再來看這張圖,是不是思路清晰多了呢!

當你弄清楚了原型鏈(我喜歡叫他進化鏈)__proto__,prototype之間的關系,還有Javascript中12個內置對象,其中10個函數類型,2個對象類型。再來學習這12個內置對象的屬性和屬性方法是不是如魚得水,心里跟明鏡似的~

對于Javascrip初學者,一時半會肯定還是搞不清楚,唯一的辦法就是多看、多想、多模仿、多創新、多總結、多分享~,學習的本質無非就是這些嘛,教育的本質無非就是教會你用學習的本質學習你所感興趣的嘛。

原文鏈接:http://www.shuaihuajun.com/article/javascript-prototype-chain-relationship/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容