JS 淺層複製及深層複製

JS 物件參考

講到淺層複製及深層複製就會提到 JS 的物件參考,在 JS 裡傳值(Call by value)是複製的,將 num 的值複製到num2的新記憶體區域,例如以下

var num = 1;
var num2 = num;

而物件(陣列,函式)是利用call by reference,來看範例

var people = { name: "Joe" };
var people2 = people;
people2.name = "Amy";
console.log(people == people2); // true
console.log(people); // {name: 'Amy'}
console.log(people2); // {name: 'Amy'}

可以看到上面的範例,people2是參考people的記憶體位置,所以在people2更改name的值時,也會更改到people的值,因為他們指向同一個記憶體位置

如要重新附值,需要使用以下

var people = { name: "Joe" };
var people2 = people;
people2 = { name: "Amy" };
console.log(people == people2); // false
console.log(people); // {name: 'Joe'}
console.log(people2); // {name: 'Amy'}

但在函式裡面重新賦值,外面的變數都不會變,所以就是屬於 pass by value。

淺層複製 shallow copy

以下是淺層複製的範例,可以看到利用以下方法只能改變第一層,可以發現members都指向同個記憶體

var family = {
name: "Joe家",
members: {
father: "爸",
mom: "媽",
brother: "弟",
},
};

var newFamily = {};
for (var key in family) {
newFamily[key] = family[key];
}
newFamily.name = "Amy家";
console.log(family === newFamily); // false
newFamily.members.brother = "Timmy";
console.log(family, newFamily);

jQuery

var newFamily2 = jQuery.extend({}, family);

ES6

var newFamily3 = Object.assign({}, family);

深層複製 deep copy

先將物件轉成字串,再賦予給新變數,就可以將值複製到新的記憶體區域

var newFamily4 = JSON.parse(JSON.stringify(family));
newFamily4.name = "Amy家";
newFamily4.members.brother = "Timmy";
console.log(family === newFamily4); // false