閱讀花費時間:2分鐘
這是一個非常簡短的值和引用的解釋。
首先,對於每一個JavaScript開發者來說,值(value)和引用(reference)的定義,一般是從一些bug被引出的,而且在面試中也經常會被問到。這篇文章中也將簡單的涵蓋這些基本概念。
別先急著往下滑,你知道下面這些程式碼會有什麼結果嗎?
console.log([10] === [10]);
複製程式碼
var oldArray = [];
var object = {};
object.newArray = oldArray;
oldArray.push(10);
console.log(object.newArray === oldArray);
複製程式碼
第一個例子是 false 而第二個例子是 true。你答對了麼,我們來看看這是為什麼:
在 JavaScript 中,有一些型別和值是直接複製了引用,分別是下面的這些:
原始值 (複製值)
- null
- undefined
- Number
- String
- Boolean
物件 (複製引用)
- 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
複製程式碼
當我們把沒有初始值的物件賦給變數時,我們只是複製了他的引用。如此可以想象,宣告變數a
時,我們在記憶體裡面創造了一個新的地址,在宣告b
的時候,b
就直接指向了那個地址,所以我們更新這個地址的內容的時候,a
和 b
有著相同的值。
var a = []; # 地址 #001 -> []
# 變數 a -> #001
var b = a; # 變數 b -> #001
a.push(1); # 地址 #001 -> [1]
變數 | 地址 | 值
a | #011 | [1]
b | #011 | [1]
複製程式碼
關於 [10] === [10] 的例子
當我們比較物件的時候,相等運算子(===)會檢查他們是否指向相同的地址。所以如果[10]
和[10]
是兩個不同的陣列,結果就會返回false
。當你想要對比兩個物件或者陣列是不是相同的方法很簡單,但是這樣的方法也很有限
JSON.stringify(a) === JSON.stringify(b)
複製程式碼
儘管這樣的方法在陣列和物件內部順序不一樣的時候,還是會出錯。如果你想要更健壯的解決方法的話,參考lodash _.isEqual() method,或者通過這個stackoverflow 回答 來自己實現一個解決方案。
作者:Miro Koczka
原文:Back to roots: JavaScript Value vs Reference
翻譯:Dominic Ming