JavaScript萬物產生順序

天翊發表於2018-11-01

這篇文章的思想主要來源JavaScript 世界萬物誕生記,最後結合一些理解梳理下網上比較經典的一些問題,下次發文章一定會把這些連結帶上

我們在很多地方可能都有聽說過一種說法——JavaScript 萬物皆物件。雖然這種說法不是特別準確,因為我們知道 undefined 就不是個物件,但不可否認的是 JavaScript 中大部分資料都是物件,那麼問題來了,物件產生的先後順序是什麼呢?對於 Object 來說,它是一個 Function的例項,因為 Object instanceof Function // true;對於 Function 來說,它是 Object 的例項,因為 Function instanceof Object // true,所以到底是先有 Object 還是先有 Function呢?這篇文章主要向大家介紹了 JavaScript 物件的產生過程

混沌初始

我們可以把 JavaScript 世界當作是一家自給自足的工廠,這家工廠可以理解為我們的V8引擎,起初工廠中什麼都沒有,但是工廠認為沒有東西本身就是一種東西呀,所以 null 就出現了

萬物之始

工廠想創造一些物品(也就是物件)出來,但是現在沒有建立物品的(模版原料),所以工廠就基於 null 造出來一個模版

JavaScript萬物產生順序

這個物件可厲害了,是 JavaScript 中物件的始祖,所有的物件追根溯源後都會找到這個物件,這個天字一號元素就是 JavaScript 中的 Object.prototype,因此在 JavaScriptObject.prototype.__proto__ === null

製造物件的機器

好了,既然模版已經存在了,工廠基於這個一個個手動建立不就好了嗎?但是這樣的工廠效率太低下了吧,於是工廠靈機一動,造出了一個機器,用於建立物品(物件)出來,而這些物品的模板就是上述提到的天字一號元素 Object.prototype

JavaScript萬物產生順序

現在我們就可以基於這臺機器來源源不斷的建立物品了,它的模版是 Object.prototype

JavaScript萬物產生順序

我們通過 new Object 建立一個物件,由於它是以天字一號元素為模板,因此 new Object({}).__proto__ === Object.prototype

製造不同物件的機器

現在工廠可以建立很多個這樣的物品,但是這樣對於工廠來說太單調了,工廠突然有個了想法,我們可以造出更多的機器(也就是 JavaScript 中的 ArrayString等等)來創造出來不同的物品呀,但是對於機器來說,他本身也是一種物件,現在有了這麼多機器,要把這類的機器物件和我建立出來的具體物品物件給區別開來,於是工廠基於天字一號元素建立天字二號元素

JavaScript萬物產生順序

這個天字二號元素是機器的模版物件,也就是說,每個機器都是它的例項

JavaScript萬物產生順序

製造機器的機器

好了,現在工廠的世界豐富了起來,不同的機器建立了不同的物品,大家彼此其樂融融,過了一段時間,外部的世界有了一個需求,我不想要這樣的物品,你給我建立一個不同的吧,工廠心想,如果每次都這樣,自己豈不是要累死,於是它建立了一個超級厲害的東西,建立機器的機器,也就是我們所說的 Function,由於他是建立機器使用的,所以它的模版物件是天字二號元素;但是他本來又是一臺機器,所以天字二號物件的例項

Function.__proto__ === Function.prototype
複製程式碼

這也是 JavaScript 中最著名的雞生蛋還是蛋生雞的問題

JavaScript萬物產生順序

問題來了

好了現在整個 JavaScript 的世界都正常了,但是這個建立過程還有幾點疑問,留給自己慢慢思考

  • 天字一號元素 Object.prototype 是怎麼通過 null 建立出來的呢
  • Function.__proto__ === Function.prototype;
    Function 建構函式的 prototype 屬性和 __proto__ 屬性都指向同一個原型,是否可以說 Function 物件是由 Function 建構函式建立的一個例項

經典圖片

JavaScript萬物產生順序

這張圖有助於理解 FunctionObject 的關係,下面通過自己畫一張圖片來解釋一些每條線的解釋

JavaScript萬物產生順序
  • 紅色的線:new Object() 的模版物件是 Object.prototypeObject 的原型物件是 Object.prototype,它的模版物件是 Function.prototypeObject.prototype 的模版物件是 null
new Object().__proto__ === Object.prototype;
Object.__proto__ === Function.prototype;
Object.prototype.__proto__ === nulll;
複製程式碼
  • 黃色的線:Function 的原型物件和模板物件都是 Function.prototypeFunction.prototype的模板物件是 Object.prototype
Function.prototype === Function.__proto__;
Function.prototype.__proto__ === Object.prototype;
複製程式碼
  • 黑色的線:new Foo() 的模版物件是 Foo.prototypeFoo.prototype的模版物件是 Object.prototypeFoo的模版物件是 Function.prototype
new Foo().__proto__ === Foo.prototype;
Foo.prototype.__proto__ === Object.prototype;
Foo.__proto__ === Function.prototype
複製程式碼

參考文章

相關文章