B復(fù)制A道偷,A改變,B改變則為淺拷貝记劈,不改變?yōu)樯羁截?/p>
基本類型 名值存儲在棧內(nèi)存中 -- 深拷貝
簡單的來說就是,在有指針的情況下并巍,淺拷貝只是增加了一個指針指向已經(jīng)存在的內(nèi)存目木,而深拷貝就是增加一個指針并且申請一個新的內(nèi)存,使這個增加的指針指向這個新的內(nèi)存懊渡,采用深拷貝的情況下刽射,釋放內(nèi)存的時候就不會出現(xiàn)在淺拷貝時重復(fù)釋放同一內(nèi)存的錯誤!
在js中剃执,對于非基本類型數(shù)據(jù)(普通對象或數(shù)組)誓禁,淺拷貝只是拷貝了內(nèi)存地址,子類屬性指向父類屬性的內(nèi)存地址肾档,而子類修改后父類也會被修改
基本類型復(fù)制.png
引用數(shù)據(jù)類型 名存儲在棧內(nèi)存中摹恰,值存在堆內(nèi)存中 棧內(nèi)存會提供一個引用的地址指向堆內(nèi)存中的值
引用數(shù)據(jù)復(fù)制.png
法一:
通過遞歸實現(xiàn)封裝一個對象({}|[])深拷貝的函數(shù) 深拷貝拷貝對象各個層級的屬性
function deepClone(obj) {
let cloneObj = Array.isArray(obj)?[]:{}
if(obj && typeof obj == "object"){
for(let key in obj) {
if(obj[key] && typeof obj[key] === "object"){
cloneObj[key] = deepClone( obj[key] )
}else {
cloneObj[key] = obj[key]
}
}
}
return cloneObj;
}
let a = [1,2,3,4]
b = deepClone(a)
a[0] = 2
console.log(a,b)
===>a:[2,2,3,4] b:[1,2,3,4]
slice()和conca方法并不是深拷貝,元素只有一級時怒见,可以實現(xiàn)深拷貝俗慈,子對象里還有對象,就無法實現(xiàn)
let a = [1,2,3,4]
b = a.slice()
a[0] = 2;
console.log(a,b)
===>a:[2,2,3,4] b:[1,2,3,4]
let a = [1,2,[2,3],4]
b = a.slice()
a[0] = 2;
a[2][0] = 1
console.log(a,b)
===>a:[2,2,[1,3],4] b:[1,2,[1,3],4]
===>拷貝不徹底遣耍,一級屬性的確不受影響闺阱,但二級屬性沒拷貝成功,所以不是真正的深拷貝
法二:
借用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);
法三
借用JQ的extend方法
$.extend([deep],target,object1[,objectN])
deep表示是否深拷貝舵变,為true為深拷貝酣溃,為false瘦穆,則為淺拷貝
target Object類型 目標(biāo)對象,其他對象的成員屬性將被附加到該對象上赊豌。
object1 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);