JavaScript - Value vs. Reference

在 JavaScript 環境中,如果你輸入:

1
2
console.log( [] == [] );
console.log( {} == {} );

兩個 log 得到的會是 true 還是 false ?

答案都是: false

再來看看其他例子

1
2
3
4
5
6
var object1 = {value: 10};
var object2 = object1;
var object3 = {value: 10};

console.log(object1 == object2); // true
console.log(object1 == object3); // false

為什麼 object1 跟 object3 裡面的值一樣,卻不相等?

JavaScript 的 物件 與 一般變數 在存取時,是有不同的機制的,一般變數不論是 字串、Number、Boolean、Null…,變數在賦值時,指向的是它的 Value,Value 相等比較出來結果也會相等,而 Object 就不同了,在宣告一個變數是 Object 或 Array 時,等於是創建了一個獨一無二的空間,拿兩個不同的空間比較,結果當然也就是 false

陣列也是 Pass By Reference

JavaScript 中,陣列也是物件的一種,同樣需要注意在複製、修改時,都必須要小心,看看幾個例子:

1
2
3
4
5
6
let a = [1, 2, 3, 4];
let b = a;
let c = [1, 2, 3, 4];

console.log(b === a); // true
console.log(c === a); // false

那在 JavaScript 中陣列有什麼方法能 clone 呢?

  • 使用 concat,concat 是合併成一個新的陣列,不會修改到原本陣列

1
2
3
4
let a = [1, 2, 3, 4];
let b = [].concat(a);

console.log(a === b) //false

  • 在 ES6 可以使用 […Array]

1
2
3
4
let a = [1, 2, 3, 4];
let b = [...a];

console.log(a === b) //false

Object 同樣也有方法能做到 clone

  • 使用 Object.assign({}, Object)

1
2
3
4
let a = {x: 1, y: 2, z: 3};
let b = Object.assign({}, a);

console.log(a === b) //false

  • 在 ES6 可以使用 {…Object}

1
2
3
4
let a = {x: 1, y: 2, z: 3};
let b = {...a};

console.log(a === b) //false

  • 但是在 Object 使用上面兩種方法還有一個大問題,如果 Object 裡面還有一層 Object 那會造成只有第一層被 clone 的情況,這種多層 Object 就不建議使用上面兩種方式,而是使用一個特殊的方法,JSON.parse(JSON.stringify),把 Object 轉成 JSON 字串,再轉回 JSON Object

1
2
3
4
5
let a = {x: 1, y: 2, z: {i = 999}};
let b = JSON.parse(JSON.stringify(a));

console.log(a === b) //false
console.log(a.z === b.z) //false

  • 但是這也不是個完美的方法,如果 Object 很大一包 JSON.parse 和 JSON.stringify 是會造成效能問題的,所以使用時還是需要多加考量
Data Structure - Array Coding Problems - Google 工程師 Coding 面試範例

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×