跳至主要内容

[JS] 淺拷貝 & 深拷貝

TL;DR

我們都知道JS中的物件與陣列都具有傳參考的特性,這邊就不贅述。僅簡單紀錄拷貝的方式。

參考資料

相關連結


淺拷貝(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}