我們昨天有提到了物件 call by reference 的特性。但是問題來了,如果我真的只是單純要複製物件的值而已,不希望在複製後,只要更動其值,原變數也會受到影響(淺拷貝),該怎麼做呢?
這就是今天要分享的 深拷貝
~
那該怎麼單純的取物件的值呢?
b = {xxx}
,這種寫法將會使 b 存放的值,指向一個新的記憶體位置
。var a = {value: 123}
var b = a;
b = {value: 456};
console.log(a.value); // 123
console.log(b.value); // 456
可以看到 b
的 value 改變為 456,但是 a
的 value 還是 123。
同樣的範例還有這個,我們直接把想從 a
取出的值放到屬性名稱後面,
var a = {name: 'Ted', age: 18};
var b = {name: a.name, age: a.age};
b.name = "changed";
console.log(a.name); // Ted
console.log(b.name); // changed
懶得像上方手動複製,可以使用此方法
var a = {name: 'Ted'};
var b = Object.assign({}, a);
b.name = "Ray";
console.log(a.name); // Ted
console.log(b.name); // Ray
一樣可以觀察到,物件 b
的 name 改變時,物件 a
不會受到影響。
但是沒這麼簡單,以上方法只能拷貝一層,也就是可能會發生以下狀況,
請問 Q1
、Q2
分別為多少?
var a = {
name: 'Ted',
language: {
chinese: 'nice',
english: 'nice'
}
};
var b = Object.assign({}, a);
b.name = "Bob";
b.language.chinese = 'bad';
console.log(a.name); // Q1=?
console.log(a.language.chinese); // Q2=?
答案是,
Ans:Q1
= TedQ2
= bad
注意到了嗎?
物件 b
改變 name 並不會影響物件 a
的 name,但是改變再深一層的物件的值,就會影響到原本 a
的 language.chinese 了!
當初遇到這個問題爬了一下文,才知道原來這是很熱門的問題,也是面試常常會被問到的XD
那該怎麼解決呢?
// 網路上自己找QAQ
JSON
再 parse 回來var a = {
name: 'Ted',
language: {
chinese: 'nice',
english: 'nice'
}
};
var b = JSON.parse(JSON.stringify(a));
b.name = "Bob";
b.language.chinese = 'bad';
console.log(a.name); // Ted
console.log(a.language.chinese); // nice
使用第三方套件(ex: JQuery、lodash)
var a = {
name: 'Ted',
language: {
chinese: 'nice',
english: 'nice'
}
};
var cloneA = cloneDeep(a);
深、淺拷
貝對應的參數是可選的,為 true 或 false。淺拷貝
,那就什麼參數都不用帶,預設就是 false。var a = {};
var b = {
name: 'Ted',
language: {
chinese: 'nice',
english: 'nice'
}
};
// 深拷貝
$.extend(true, a, b);
a.language.chinese = 'bad';
// b 並沒有因為 a 的改動也跟著改動
console.log(b.language.chinese); // nice
// ----------我是分隔線-----------
// 至於沒有加上參數就是淺拷貝
$.extend(a, b);
那今日的分享就到這邊,明天會介紹一些物件在 ES6 中的操作。
我們明天見