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

a.jpg
當你b=a復制時,棧內存會新開辟一個內存,例如這樣:

b.jpg
如果此時修改a=2,并不會影響b的值,但是深拷貝一般是指復雜的object類型的數據。
引用數據類型--名存在棧內存中,值存在于堆內存中,但是棧內存會提供一個引用的地址指向堆內存中的值

c.jpg
當b=a時,復制的是a的一個引用地址,指向堆內存的值

d.jpg
當我們對a[0]=1進行修改時,堆內存里面的值也被改變了

e.jpg
堆內存中也開辟一個新的內存專門為b存放值,就像基本類型那樣,就達到深拷貝的效果了

f.jpg
實現深拷貝的方法
1.遞歸復制
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判斷ojb子元素是否為對象,如果是,遞歸復制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,簡單復制
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方法
語法:$.extend( [deep ], target, object1 [, objectN ] ),
deep:true是深拷貝,false是淺拷貝,
target:Object類型 目標對象,其他對象的成員屬性將被附加到該對象上。,
object1:可選,可選。 Object類型 第一個被合并的對象。,
objectN:可選。 Object類型 第N個被合并的對象。
let a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b)
3.JSON對象的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方法可以拷貝一級屬性但是不能拷貝二級及以下,所以不是深拷貝
文章來源:
https://www.cnblogs.com/echolun/p/7889848.html,
https://zhuanlan.zhihu.com/p/26282765,
https://www.cnblogs.com/penghuwan/p/7359026.html#_label0