[譯]基礎中的基礎,JavaScript中的值和引用
前幾天忽然發現github上有一個大熱門專案 —— “33 concepts every JavaScript developer should know ”,目前已經將近25000個Stars。這個專案旨在幫助前端開發者掌握33個JavaScript基礎概念。按作者話說,這些概念並不是開發所必需的,但它們是引導你通向前端大牛之路的基石。
遺憾的是,該專案中文版的文章收錄不盡完整。所以本著學習與交流的目的,本人會把33個概念所涉及的文章利用業餘時間竭盡所能的翻譯出來,其中不免疏漏,望請指正。今天是第三篇 ,以下為正文:
基本型別和引用型別 ,是我們作為前端開發所必需掌握的知識,不僅因為人們容易混淆其概念從而經常引起BUG,它還是面試中經常出現的一類問題。
我爭取在這篇短文中,儘可能簡單的闡述這個基礎概念。
先彆著急往下翻,你知道以下兩個例子的結果嗎?
示例1:
console.log([10] === [10]); 複製程式碼
示例2:
var oldArray = []; var object = {}; object.newArray = oldArray; oldArray.push(10); console.log(object.newArray === oldArray); 複製程式碼
第一個結果是false
,第二個結果是true
。你答對了嗎?我們來看看為什麼會是這樣。
在JavaScript中,我們以值的複製和值的引用來區分兩種型別。他們是
基本型別(值的複製)
- null
- undefined
- Number
- String
- Boolean
- symbol
物件型別(值的引用)
- Object
- Array
- Function
基本型別
var a = 5; var b = a; a = 10 console.log(a); // 10 console.log(b); // 5 // string, boolean, null, undefined同理 複製程式碼
我們把基本型別的值賦給變數,相當於把這個值複製一份,賦給另一個變數。
物件型別
注意哦,讓人困惑的部分來了
var a = {}; var b = a; a.a = 1; console.log(a); // {a: 1} console.log(b); // {a: 1} 複製程式碼
陣列同理。
var a = []; var b = a; a.push(1); console.log(a); // [1] console.log(b); // [1] console.log(a === b); // true 複製程式碼
當我們把物件型別賦給變數,相當於複製一個引用地址。該地址是宣告變數時在記憶體中創建出來的。宣告變數b
時,僅僅是把這個地址的引用賦給它。所以我們更新該地址時,兩個變數的值相同。
var a = [];# Address #001 -> [] # Variable a -> #001 var b = a;# Variable b -> #001 a.push(1);# Address #001 -> [1] 複製程式碼
Variable | Address | Value |
---|---|---|
a | #011 | [1] |
b | #011 | [1] |
此時,我們再來看看“[10] === [10]
”的例子
對比兩個陣列,全等操作符會檢查它們是否指向同一個地址。所以,如果兩個[10]不是同一個陣列,結果為false
。如果你想要對比兩個陣列或物件的值是否相同,倒是有一個簡單但又限制頗多的方法。
JSON.stringify(a) === JSON.stringify(b) 複製程式碼
這樣做的缺點是,物件或陣列的屬性順序不同時會返回false
。如果你想要更加健全的辦法,可以選擇lodash庫中的isEqual()
方法。
下一篇講述隱式轉型,敬請期待。