又有人會稱作 淺拷貝 以及 深拷貝
而深跟淺是怎麼樣定義的呢?我們就一樣先來看例子說明吧!
var family = {
name: '小明家',
members: {
father: '老爸',
mom: '老媽',
ming: '小明'
}
};
有的時候我們會希望用另一個變數,複製相同結構的物件,但我們又不希望他們指向的是同一個記憶體空間,除了之前提到的用 物件實字 的方式宣告之外,還有沒有其他的辦法呢?
這裡提供兩種辦法,就是所謂的 淺拷貝 以及 深拷貝
淺拷貝指的就是沒有辦法每一層的物件都完全脫鉤,包含三種方法,先以 for-in
的迴圈舉例
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 之後,就完成 淺拷貝。
印出來以後可以看到兩個物件的內容都長得一樣
如果我今天改動 family2.member.ming = '大明';
的時候,family.member.ming
也會跟著改動喔,因為他們兩個物件中的子物件都還是 指向同一個記憶體位置的狀態。
所以這就是淺拷貝的特點,雖然第一層是分開的,但第二層之後卻還是有可能造成 call by reference(註1)的狀況。
所以反之,深拷貝就是連物件中的子物件都會指向不同的記憶體空間,並且保持內容結構都一模一樣。
var family = {
name: '小明家',
members: {
father: '老爸',
mom: '老媽',
ming: '小明'
}
};
// jQuery extend
var family3 = jQuery.extend({}, family);
console.log(family, family3);
var family = {
name: '小明家',
members: {
father: '老爸',
mom: '老媽',
ming: '小明'
}
};
// ES6 Object.assign
var family4 = Object.assign({}, family);
console.log(family, family4);
主要就是先把物件變成字串,再轉回物件,這樣他傳參考的特性就會消失了喔!
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)。