iT邦幫忙

2

Javascript 進階 4-9 淺層複製及深層複製

今天要討論的主題是淺層複製及深層複製

又有人會稱作 淺拷貝 以及 深拷貝

而深跟淺是怎麼樣定義的呢?我們就一樣先來看例子說明吧!

var family = {
    name: '小明家',
    members: {
        father: '老爸',
        mom: '老媽',
        ming: '小明'
    }
};

有的時候我們會希望用另一個變數,複製相同結構的物件,但我們又不希望他們指向的是同一個記憶體空間,除了之前提到的用 物件實字 的方式宣告之外,還有沒有其他的辦法呢?

這裡提供兩種辦法,就是所謂的 淺拷貝 以及 深拷貝

淺層複製(淺拷貝)、Shallow Copy

淺拷貝指的就是沒有辦法每一層的物件都完全脫鉤,包含三種方法,先以 for-in 的迴圈舉例

1. for-in loop

var family = {
    name: '小明家',
    members: {
        father: '老爸',
        mom: '老媽',
        ming: '小明'
    }
};

var family2 = {};
for(key in family) {
    console.log(key); // family 物件第一層有幾個屬性就跑幾次
    family2[key] = family[key];
}

console.log(family, family2);

這邊的 key 不一定要叫做 key,你可以任意取名字,當 for-in 迴圈用在物件的時候,則會依照該物件的 第一層屬性有幾個就跑幾次,以 family 的物件來說,第一層有 name 以及 members 兩個屬性,所以跑兩次,而 key 就會是 屬性的名稱 ,所以跑第一次的時候 key 是 name ,第二次的時候 key 是 members

所以在依照這樣的模式將值塞入 family2 之後,就完成 淺拷貝

印出來以後可以看到兩個物件的內容都長得一樣

https://ithelp.ithome.com.tw/upload/images/20200103/20121770rdnfV7CSVX.png

但是!!!!

如果我今天改動 family2.member.ming = '大明'; 的時候,family.member.ming 也會跟著改動喔,因為他們兩個物件中的子物件都還是 指向同一個記憶體位置的狀態。

https://ithelp.ithome.com.tw/upload/images/20200103/20121770JewbnCrCOL.png

所以這就是淺拷貝的特點,雖然第一層是分開的,但第二層之後卻還是有可能造成 call by reference(註1)的狀況。

所以反之,深拷貝就是連物件中的子物件都會指向不同的記憶體空間,並且保持內容結構都一模一樣。

2. jQuery extend

var family = {
    name: '小明家',
    members: {
        father: '老爸',
        mom: '老媽',
        ming: '小明'
    }
};

// jQuery extend

var family3 = jQuery.extend({}, family);

console.log(family, family3);

3. ES6 Object.assign

var family = {
    name: '小明家',
    members: {
        father: '老爸',
        mom: '老媽',
        ming: '小明'
    }
};

// ES6 Object.assign

var family4 = Object.assign({}, family);

console.log(family, family4);

深層複製(深拷貝)、Deep Copy

主要就是先把物件變成字串,再轉回物件,這樣他傳參考的特性就會消失了喔!

var family = {
    name: '小明家',
    members: {
        father: '老爸',
        mom: '老媽',
        ming: '小明'
    }
};

var deepFamily = JSON.parse(JSON.stringify(family));

console.log(family, deepFamily);

以上就是本篇文章的內容,希望對各位有幫助~汪汪

註1: 雖然上一篇文章提到 Javascript 是 call by sharing,但這裡是用行為去描述,可以參考上一篇文章附的進階文章內容。結論是依照不同行為的狀況進行不同的分類(call by value/ reference / sharing)。


尚未有邦友留言

立即登入留言