剖析JS 「萬物皆物件」的迷思
· 閱讀時間約 7 分鐘
初學 JavaScript 時,偶爾會在教學文或討論區中看到這樣的說法:
「在 JavaScript 中,萬物皆為物件。」
便在潛意識中埋下一個 JS 中所有變數都是物件的種子。如今因為工作上大量使用 JS 這個語言,對 JS 這個語言有比較深一點的了解後,便想要回來探討這個議題。
先講結論,這個說法是不正確的。
但是,我相信正在看這篇文章的你應該也跟我一樣,會想要了解為什麼訪間會有 「JavaScript 萬物皆為物件」 的說法,以及這個說法背後的論點是什麼?反對這個說法的論點是什麼?本篇文章將帶大家探討這個議題,挖掘正反兩方的論點,並釐清一些 JS 的觀念。
為何會有「萬物皆物件」的說法?
JavaScript 的基本資料型別
在探討 「萬物皆為物件」 這個議題之前,我們首先需要了解 JavaScript 中的基本資料型別。JavaScript 中有七種資料型別,Undefined、Null、Boolean、Number、String、Symbol(ES6新增)、Object。其中,前六種是基本資料型別(Primitive Types),而 Object 是複雜資料型別。
由此可見,在 JavaScript 的世界中,並非所有的資料型別本質上都是物件。基本資料型別是獨立的,它們並不具備物件的屬性和方法。然而,在某些情況下,基本資料型別也可以表現出類似物件的行為,這正是 「萬物皆物件」 這種說法產生的原因之一。
「萬物皆物件」說法的起源
雖然基本資料型別和物件有著明顯的區別,但在實際使用中,我們常常發現基本資料型別可以像物件一樣操作。例如:
const a = "123";
console.log(a.__proto__)
/* String {
anchor: ƒ anchor()
at: ƒ at()
big: ƒ big()
blink: ƒ blink()
bold: ƒ bold()
charAt: ƒ charAt()
charCodeAt: ƒ charCodeAt()
codePointAt: ƒ codePointAt()
concat: ƒ concat()
constructor: ƒ String()
...
} */
const b = "456";
console.log(b.substr(1)); // "56"
從上述例子中可以看到,變數 a 和 b 雖然是基本資料型別 String,但它們都有 __proto__
屬性,並且可以調用多種方法。這似乎印證了 「基本型別也是一種物件」 的說法。