一、深拷貝和淺拷貝的概念
舉個(gè)栗子:
var a = {name:'Jack'};
var b = a;
b.name = 'Peter';
console.log(a.name) //'Peter'
從以上代碼可以看出,當(dāng)a是一個(gè)對(duì)象的時(shí)候,將a賦值給b,則b的屬性改變之后a的屬性也會(huì)相應(yīng)的改變(因?yàn)樗鼈冎赶蛄送粔K內(nèi)存),這就是淺拷貝。
與之相反的,若將a的屬性復(fù)制到b,而b重新指向另一塊內(nèi)存,則b里的屬性變化時(shí),a的屬性將不會(huì)被改變,這就是深拷貝。
并且,JavaScript中的七種數(shù)據(jù)類型中,基本類型(String、Number、Boolean、Symbol、null、undefined)在拷貝的時(shí)候,結(jié)果都符合深拷貝的定義,因此不在我們的討論范圍。
二、實(shí)現(xiàn)淺拷貝
1、直接賦值
var obj1 = {a:1,b:2};
var obj2 = obj1;
obj2.a = 3;
console.log(obj2)//{a:3,b:2}
console.log(obj1)//{a:3,b:2}
2、用Object.assign()來(lái)實(shí)現(xiàn)
var obj1 = {a:1,b:{b1:2,b2:3}};
var obj2 = Object.assign({},obj1);
obj2.b.b1 = 4;
console.log(obj2)//{a:1,b:{b1:4,b2:3}}
console.log(obj1)//{a:1,b:{b1:4,b2:3}}
值得注意的是,當(dāng)obj1里的數(shù)據(jù)只有一層時(shí),Object.assign()是深拷貝
var obj1 = {a:1,b:2};
var obj2 = Object.assign({},obj1);
obj2.a = 3;
console.log(obj2)//{a:3,b:2}
console.log(obj1)//{a:1,b:2}
三、實(shí)現(xiàn)深拷貝
1、用遞歸實(shí)現(xiàn)
var Jack = {
name : 'Jack',
nationality :'US',
friends:['Sally','Ryan']
};
function deepCopy(o,c){
var c = c || {}
for(var i in o){
if(typeof o[i] === 'object'){
if(o[i].constructor === Array){
c[i] =[]
}else{
c[i] = {}
}
deepCopy(o[i],c[i])
}else{
c[i] = o[i]
}
}
return c
};
var Peter = {};
deepCopy(Jack,Peter);
Peter.name = 'Peter';
console.log(Peter) //{name:'Peter',nationality:'US',friends:['Sally','Ryan']}
console.log(Jack)//{name:'Jack',nationality:'US',friends:['Sally','Ryan']}
2、用JSON.parse()和JSON.stringfy()來(lái)實(shí)現(xiàn)
var target = {a: 1, b: 1, c: {c1: 11, c2: 12, c3: 13}};
var deepCopy = JSON.parse(JSON.stringify(target));
deepCopy.a = 2;
deepCopy.c.c1 = 21;
console.log(target); // {a: 1, b: 1, c: {c1: 11, c2: 12, c3: 13}}
console.log(deepCopy); // {a: 2, b: 1, c: {c1: 21, c2: 12, c3: 13}}
console.log(target === deepCopy); // false
注:JSON.parse()和JSON.stringfy()能夠正確處理的只有String、Number、Array等能夠被json表示的數(shù)據(jù)類型,不能被json表示的會(huì)丟失。
var target = {a:1,b:1,c:function(){console.log('hi')}};
var deepCopy = JSON.parse(JSON.stringfy(target));
console.log(deepCopy)//{a:1,b:1}
3、用jQuery.extend()來(lái)實(shí)現(xiàn)
var target = {a:1,b:1,c:{c1:11,c2:12,c3:13}};
var deepCopy = $.extend(true,{},target)
deepCopy.c.c2 = 22
console.log(deepCopy)//{a:1,b:1,c:{c1:11,c2:22,c3:13}}
console.log(target)//{a:1,b:1,c:{c1:11,c2:12,c3:13}}