iT邦幫忙

1

JavaScript 基礎知識 - 淺複製(shallow copy)和深複製(deep copy)

前一篇結尾講到了物件的傳參考的特性,但有時候我們希望屬性和值是被直接複製一份,並非是直接指向的

淺複製(shallow copy)

如果用一般比較傳統的方式,會使用 for in 的作法:

var person = {
    name: 'Jerry',
    members: {
        father: 'John',
        mother: 'Mary'
    }
};

var person2 = {};

for(var key in person){
    person2[key] = person[key]
}

這時候如果在 person2 更改 name 屬性,person 是不會被影響的,這是因為當命名 person2 為空物件的時候,已經把它指向另外一個記憶體空間,接著把 person 的屬性用 for 迴圈一一的傳遞給 person2,就可以把一個物件複製

當然 ES6 提供了一個不錯的方法可以做使用 Object.assign(),方法內是一個空物件跟要被複製的物件變數:

var person2 = Object.assign({}, person);

這個方法結果會跟上面是一樣的,只是更為簡潔好用

上面所講的都是淺複製,為什麼是淺複製呢 ?
因為當我們嘗試去更改 person2 的 members 物件屬性的內部屬性時,person 的 members 屬性也被做更動了,這是因為 members 這個物件屬性,它也是一個物件,所以也是獨立的記憶體空間,即使複製了,指向的位置依然沒有變動

所以為了這種多層次的物件,有另外一種複製的方式

深複製(deep copy)

聽起來雖然很深奧,但其實只是運用了 JavaScript 的轉字串跟轉物件的方式而已

// 首先先把物件格式轉成字串
JSON.stringify(person);

// 再轉回去物件,並賦予一個變數
var person3 = JSON.parse(JSON.stringify(person));

轉完之後,先來更改一下 person3 的物件屬性 members 的 mother 屬性
person3.members.mother = 'Anna';

再用 console 分別查看 person 和 person3 的物件屬性 members 的 mother 屬性

console.log(person.members.mother, person3.members.mother);
// Mary, Anna

就會發現資料已經不會互相影響了,進一步一樣可以用 === 來檢查

console.log(person.members === person3.members);
// false

這樣彼此的 members 物件屬性就分別指向不同的記憶體空間,也完成了物件屬性的複製
這就是深複製(deep copy)


尚未有邦友留言

立即登入留言