[JS] 淺拷貝 & 深拷貝
TL;DR
我們都知道JS中的物件與陣列都具有傳參考的特性,這邊就不贅述。僅簡單紀錄拷貝的方式。
參考資料
- 關於JS中的淺拷貝(shallow copy)以及深拷貝(deep copy)(Andy Chen) | Medium
- JS基本觀念:call by value 還是reference 又或是 sharing?(Charles Huang) | Medium
相關連結
- Object.assign() | MDN
淺拷貝(Shallow copy)
淺拷貝有兩種比較簡單的方式,一種是展開運算子(Spread operator)
,另一種是Object.assign()
。
程式碼範例如下:
const person = {
name: '小明',
obj: {}
}
const person2={...person};
const person3=Object.assign({},person);
console.log(person,person2,person3,person===person2,person===person3);
雖然使用===
去判斷都會返回false
(物件的===判斷是使用記憶體位置去判斷,而不是內容),但是因為是淺拷貝所以對person物件下的obj新增資料如下:
const person = {
name: '小明',
obj: {}
}
const person2={...person};
const person3=Object.assign({},person);
console.log(person,person2,person3,person===person2,person===person3);
person2.name="小華";
person2.obj.a='a';
person3.name="小傑";
person3.obj.b='b';
console.log(person,person2,person3,person===person2,person===person3);
得到結果如下,可以看到name有修改而且沒有影響到person。但是obj內的屬性則是都有新增。
這是因為淺拷貝只會拷貝第一層,第二層以下的obj仍然指向同一個記憶體空間。
深拷貝(Deep copy)
要解決第二層以下仍然參考相同的記憶體空間這個問題,目前看到唯一的方法只有先將物件轉陣列,再轉回物件的方式。
程式碼如下:
let obj1 = {a: {a: 1}}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj1.a.a = 2
console.log(obj2.a) // {a: 1}