這是我當時向一位網友提出的問題,這位網友就拿const作用域及能否改值來回答,似乎沒有明白我的問題關鍵所在。
做個試驗:
const obj1 = {
a: 36,
b: [36]
};
const obj2 = obj1;
obj2["a"] = 24;
obj2["b"][0] = 48;
console.log(obj1.a); // 24
console.log(obj2.a); // 24
console.log(obj1.b); // Array [ 48 ]
console.log(obj2.b); // Array [ 48 ]
我們發現const對於Object基本沒有用,當然Array也是一樣。也就是說,上面的const換成let也是一樣的。
如果我們將賦值方式改為Object.assign又會發生甚麼呢?
const obj1 = {
a: 36,
b: [36]
};
const obj2 = Object.assign({}, obj1);
obj2["a"] = 24;
obj2["b"][0] = 48;
console.log(obj1.a); // 36
console.log(obj2.a); // 24
console.log(obj1.b); // Array [ 48 ]
console.log(obj2.b); // Array [ 48 ]
說明這時obj2.a
的指針已經不同於obj1.a
。
對於Function, Class, Object, Array這些類型而言,值存的是指針地址。賦值也是指針地址。而assign給了obj2.a一個新的指針地址指向新的值;obj2.b仍然指向了同一個地址,因為它的數據類型是Array。
如果我們希望obj2.b也是一個新的指針呢?有兩種辦法。
一種是先delete obj2.b,再重新賦值。
第二種是deepcopy。
deepcopy最簡單的方式是json:
let b = JSON.parse(JSON.stringify(a));
但json對於空值如undifined、none、null,會統一轉為null。
因此考慮用下面的函數:
function deepCopy(obj) {
let _obj = {};
for(let key in obj) {
_obj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
return _obj;
}
這個方法會使Array轉為Object類型,問題不大。