深拷貝和淺拷貝的區(qū)別
當(dāng)A復(fù)制B的值時(shí),B改變了,A也跟著變,這就是淺拷貝;如果改變B的值,A不改變,那么就是深拷貝,是拷貝對(duì)象各個(gè)層級(jí)的屬性。
要想?yún)^(qū)分深拷貝和淺拷貝,需要先了解幾種數(shù)據(jù)類型:
基本數(shù)據(jù)類型:number,string,boolean,null,undefined
引用數(shù)據(jù)類型:對(duì)象,數(shù)組,函數(shù)
基本類型--名值存儲(chǔ)在棧內(nèi)存中,例如let a=1;

當(dāng)你b=a復(fù)制時(shí),棧內(nèi)存會(huì)新開辟一個(gè)內(nèi)存,例如這樣:

如果此時(shí)修改a=2,并不會(huì)影響b的值,但是深拷貝一般是指復(fù)雜的object類型的數(shù)據(jù)。
引用數(shù)據(jù)類型--名存在棧內(nèi)存中,值存在于堆內(nèi)存中,但是棧內(nèi)存會(huì)提供一個(gè)引用的地址指向堆內(nèi)存中的值

當(dāng)b=a時(shí),復(fù)制的是a的一個(gè)引用地址,指向堆內(nèi)存的值

當(dāng)我們對(duì)a[0]=1進(jìn)行修改時(shí),堆內(nèi)存里面的值也被改變了

堆內(nèi)存中也開辟一個(gè)新的內(nèi)存專門為b存放值,就像基本類型那樣,就達(dá)到深拷貝的效果了

實(shí)現(xiàn)深拷貝的方法
1.遞歸復(fù)制
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判斷ojb子元素是否為對(duì)象,如果是,遞歸復(fù)制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,簡(jiǎn)單復(fù)制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
2.Jq的extend方法
語(yǔ)法:$.extend( [deep ], target, object1 [, objectN ] ),
deep:true是深拷貝,false是淺拷貝,
target:Object類型 目標(biāo)對(duì)象,其他對(duì)象的成員屬性將被附加到該對(duì)象上。,
object1:可選,可選。 Object類型 第一個(gè)被合并的對(duì)象。,
objectN:可選。 Object類型 第N個(gè)被合并的對(duì)象。
let a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b)
3.JSON對(duì)象的parse和stringify
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
注意slice方法可以拷貝一級(jí)屬性但是不能拷貝二級(jí)及以下,所以不是深拷貝
文章來源:
https://www.cnblogs.com/echolun/p/7889848.html,
https://zhuanlan.zhihu.com/p/26282765,
https://www.cnblogs.com/penghuwan/p/7359026.html#_label0