var m =
var n = m;
n.a = 15;
// 這時m.a的值是多少
m.a會輸出15,因為這是淺拷貝,n和m指向的是同乙個堆,物件複製只是複製的物件的引用
var m =
var n = ;
n.a = 15;
這時的m.a的值還是10,並沒有改變,m物件和n物件雖然所有的值都是一樣的,但在堆裡面,對應的不是同乙個了,這個就是深拷貝
自己手動複製
像上面的範例,把obj1的屬性乙個個複製到obj2中:
var obj1 = ;
var obj2 = ;
obj2.b = 100;
console.log(obj1);
// <-- 沒被改到
console.log(obj2);
//
但這樣很麻煩要自己慢慢複製,而且這樣其實不是 deep copy,如果像下面這個狀況
var obj1 = };
var obj2 = ;
obj2.body.a = 20;
console.log(obj1);
// } <-- 被改到了
console.log(obj2);
// }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// true
雖然obj1跟obj2是不同物件,但他們會共享同乙個obj1.body,所以修改obj2.body.a時也會修改到舊的。
object.assign
object.assign是 es6 的新函式,可以幫助我們達成跟上面一樣的功能。
var obj1 = ;
var obj2 = object.assign({}, obj1);
obj2.b = 100;
console.log(obj1);
// <-- 沒被改到
console.log(obj2);
//
object.assign({}, obj1)的意思是先建立乙個空物件{},接著把obj1中所有的屬性複製過去,所以obj2會長得跟obj1一樣,這時候再修改obj2.b也不會影響obj1。
因為object.assign跟我們手動複製的效果相同,所以一樣只能處理深度只有一層的物件,沒辦法做到真正的 deep copy。不過如果要複製的物件只有一層的話可以考慮使用它。
轉成 json 再轉回來
用json.stringify把物件轉成字串,再用json.parse把字串轉成新的物件
var obj1 = };
var obj2 = json.parse(json.stringify(obj1));
obj2.body.a = 20;
console.log(obj1);
// } <-- 沒被改到
console.log(obj2);
// }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// false
這樣做是真正的deep copy,但只有可以轉成json格式的物件才可以這樣用,像function沒辦法轉成json。
var obj1 = };
var obj2 = json.parse(json.stringify(obj1));
console.log(typeof obj1.fun);
// 'function'
console.log(typeof obj2.fun);
// 'undefined' <-- 沒複製
要複製的function會直接消失,所以這個方法只能用在單純只有資料的物件。
jquery
jquery 有提供乙個$.extend可以用來做 deep copy。
var $ = require('jquery');
var obj1 = },
c: [1, 2, 3]
};var obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f);
// false
lodash
另外乙個很熱門的函式庫lodash,也有提供_.clonedeep用來做 deep copy
var _ = require('lodash');
var obj1 = },
c: [1, 2, 3]
};var obj2 = _.clonedeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false
關於 js 中的淺拷貝和深拷貝 JS淺拷貝與深拷貝實現方式
js淺拷貝與深拷貝只針對的是陣列 array 和物件 object 兩種引用資料型別。引用型別的資料在記憶體中分兩部分儲存,分別是儲存在棧中的引用位址和儲存在堆中的資料。淺拷貝其實拷貝的是引用型別資料的位址,兩個物件共享堆中的資料,乙個物件改變了某個屬性值,另乙個物件的屬性值也會跟著改變。而深拷貝則...
實現淺拷貝與深拷貝
js包含基本資料型別與引用資料型別兩種不同的資料型別的值,深拷貝與淺拷貝的概念只存在於引用資料型別。對於引用型別,淺拷貝是拷貝了指向這個物件堆記憶體的指標,是拷貝了對原物件引用,深拷貝是拷貝了該物件的所有屬性到乙個新的物件,若是原物件的某屬性依然引用了其他物件,那麼需要將原物件引用的其他物件一併進行...
「淺拷貝」與「深拷貝」
c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...