J 筆記 - Clone an Object

J 筆記 - Clone an Object

雖然在 JavaScript 裡的物件型別是屬於 Passing by sharing,但正常來說如果沒有傳遞到另一物件的話,正常為 Passing by Address,因此沒有辦法直接用等號 = 來更改值、而會改到址。

3 Ways to Clone Objects

1
2
3
4
5
6
7
8
9
10
11
12
13
const Array = { old: 'ES5', new: 'ES6' };

// "Spread"
{ ...Array };

// "Object.assign"
Object.assign({}, Array);

// "JSON"
JSON.parse(JSON.stringify(Array));

// RESULT:
// { old: 'ES5', new: 'ES6'};

Passing by Address

還記得 重新認識 JavaScript: Day 05 JavaScript 是「傳值」或「傳址」? 吧?基本型別的更新與傳遞會以 Passing by Value,兩者是個是各自獨立的,而物件型別則是如同開頭所述,會更改到原本的實體,因為兩者根本是指向同一個實體的!

1
2
3
4
5
6
7
8
9
var coin1 = { value: 10 };
var coin2 = coin1;

coin1.value = 100;

console.log( coin1.value );
// 100
console.log( coin2.value );
// 100

Passing by sharing

「Pass by sharing」的特點在於,當 function 的參數,如 function changeValue(obj){ ... } 中的 obj 被重新賦值的時候,外部變數的內容是不會被影響的。

1
2
3
4
5
6
7
8
9
10
var coin1 = { value: 10 };

function changeValue(obj) {
obj = { value: 123 }; // Assignment
}

changeValue(coin1);

console.log(coin1);
// { value: 10 }

說了這麼多也知道了原因之後,以下就來介紹三種複製物件的方法。注意的是,Array 的複製也有探討到 深層淺層 的問題,如同 Deep Clone Array ㄧ樣,JSON 的方式是可以複製到 深層 的,而其他兩種沒有辦法!

  1. Using Spread
1
2
3
4
5
6
const Array = { old: 'ES5', new: 'ES6' };

const SpreadCloneArray = { ...Array };

console.log(SpreadCloneArray);
// { old: 'ES5', new: 'ES6' }
  1. Using Object.assign
1
2
3
4
5
6
const Array = { old: 'ES5', new: 'ES6' };

const Object_AssignCloneArray = Object.assign({}, Array);

console.log(Object_AssignCloneArray);
// { old: 'ES5', new: 'ES6' }
  1. Using JSON
1
2
3
4
5
6
const Array = { old: 'ES5', new: 'ES6' };

const JSONArray = JSON.parse(JSON.stringify(Array))

console.log(JSONArray);
// { old: 'ES5', new: 'ES6' }

Lodash 在 deep clone 不只是適用於 Array 也同樣適用於 Object