本文中的復(fù)制也可以稱為拷貝捉兴,在本文中認(rèn)為復(fù)制和拷貝是相同的意思蝎困。另外,本文只討論js中復(fù)雜數(shù)據(jù)類型的復(fù)制問題(Object,Array等)倍啥,不討論基本數(shù)據(jù)類型(null,undefined,string,number和boolean)禾乘,這些類型的值本身就存儲在棧內(nèi)存中(string類型的實際值還是存儲在堆內(nèi)存中的,但是js把string當(dāng)做基本類型來處理 )虽缕,不存在引用值的情況始藕。
淺復(fù)制和深復(fù)制都可以實現(xiàn)在已有對象的基礎(chǔ)上再生一份的作用,但是對象的實例是存儲在堆內(nèi)存中然后通過一個引用值去操作對象氮趋,由此復(fù)制的時候就存在兩種情況了:復(fù)制引用和復(fù)制實例伍派,這也是淺復(fù)制和深復(fù)制的區(qū)別所在。
淺復(fù)制:淺復(fù)制是復(fù)制引用剩胁,復(fù)制后的引用都是指向同一個對象的實例拙已,彼此之間的操作會互相影響
深復(fù)制:深復(fù)制不是簡單的復(fù)制引用,而是在堆中重新分配內(nèi)存摧冀,并且把源對象實例的所有屬性都進(jìn)行新建復(fù)制倍踪,以保證深復(fù)制的對象的引用圖不包含任何原有對象或?qū)ο髨D上的任何對象,復(fù)制后的對象與原來的對象是完全隔離的
由深復(fù)制的定義來看索昂,深復(fù)制要求如果源對象存在對象屬性建车,那么需要進(jìn)行遞歸復(fù)制,從而保證復(fù)制的對象與源對象完全隔離椒惨。然而還有一種可以說處在淺復(fù)制和深復(fù)制的粒度之間缤至,也是jQuery的extend方法在deep參數(shù)為false時所謂的“淺復(fù)制”,這種復(fù)制只進(jìn)行一個層級的復(fù)制:即如果源對象中存在對象屬性康谆,那么復(fù)制的對象上也會引用相同的對象领斥。這不符合深復(fù)制的要求嫉到,但又比簡單的復(fù)制引用的復(fù)制粒度有了加深。
function test() {
'use strict';
// 淺拷貝
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj1.a = 1;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj2.a = 2;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
// 深拷貝
obj1 = { a: 0 , b: { c: 0}};
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 4;
obj1.b.c = 4;
console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
}