迴歸本源:JavaScript 之中的值和引用

Dominic_Ming發表於2019-03-03

閱讀花費時間: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就直接指向了那個地址,所以我們更新這個地址的內容的時候,ab有著相同的值。

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

相關文章