由于引用類型直接復(fù)制的效果是地址的復(fù)制,只是兩個變量指向了同一塊內(nèi)存嗅绸。
var a = [1,2,3];
var b = a;
b.push[4];
console.log(b);//[1,2,3,4]
console.log(a);//[1,2,3,4]
所以有了淺拷貝和深拷貝沿彭。
淺拷貝
數(shù)組的淺拷貝
var a = [1,2,3];
var b = [];
for(var i in a){
b[i] = a[i];
}
b.push(4);
console.log(a);//[1,2,3]
console.log(b);//[1,2,3,4]
對象的淺拷貝
var obj1 = {
a: '1',
b: '2',
c: '3'
}
var obj2 = {};
for(i in obj1}{
obj2[i] = obj1[i];
}
obj2['d'] = 4;
console.log(obj1);//{a: 1,b: 2,c: 3}
console.log(obj2);//{a: 1,b: 2,c: 3, d:4}
但淺拷貝只能實(shí)現(xiàn)一層的拷貝尖滚,無法實(shí)現(xiàn)更深層次的拷貝
function shallowCopy(obj1,obj2){
for(var key in obj1){
if(obj1.hasOwnProperty(key)){
obj2[key] = obj1[key];
}
}
}
var obj1 = {
fruits: ['apple', 'peach'],
num: 100
};
var obj2 = {};
shallowCopy(obj1,obj2);
obj2.fruits[0] = 'orange';
console.log(obj1.fruits[0]); //orange
console.log(obj2.fruits[0]); //orange
hasOwnProperty方法是為了防止遍歷到數(shù)組或?qū)ο蟮睦^承屬性
淺拷貝還可以通過Object.assign方法來實(shí)現(xiàn)
Object.assign()
方法用于將所有可枚舉屬性的值從一個或多個源對象復(fù)制到目標(biāo)對象喉刘。它將返回目標(biāo)對象。
Object.assign()
var obj1 = {a:1,b:{c:2,d:3}};
var obj2 = Object.assign({},obj1);
obj2.a = 4;
obj2.b.c = 5;
console.log(obj1.a);//1
console.log(obj2.a);//4
console.log(obj1.b.c);//5
console.log(obj2.b.c);//5
Array的slice和concat方法不修改原數(shù)組漆弄,只會返回一個淺復(fù)制了原數(shù)組中的元素的一個新數(shù)組睦裳。
深拷貝
通過遞歸調(diào)用淺拷貝的方式來實(shí)現(xiàn)深拷貝
function deepCopy(obj){
var objArray = Array.isArray(obj)?[]:{};
if(obj && typeof obj === "object"){
for(var key in obj){
if(obj.hasOwnProperty(key)){
if(obj[key] && typeof obj[key] === "object"){
objArray[key] = deepCopy(obj[key]);
}else{
objArray[key] = obj[key];
}
}
}
}
return objArray;
}
var obj1 = { fruits: ['apple', 'peach'], num: 100 };
var obj2 = deepCopy(obj1);
obj2.fruits[0] = 'orange'; console.log(obj1.fruits[0]); //apple
console.log(obj2.fruits[0]); //orange
還可以通過Json.parse實(shí)現(xiàn)深拷貝
var obj1 = {a:1,b:{c:2,d:3}};
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.a = 4;
obj2.b.c = 5;
console.log(obj1.a);//1
console.log(obj2.a);//4
console.log(obj1.b.c);//2
console.log(obj2.b.c);//5
原理:用JSON.stringify將對象轉(zhuǎn)成字符串撼唾,再用JSON.parse把字符串及解析成對象,一去一來蛛蒙,新的對象產(chǎn)生了,而且對象會開辟新的棧牵祟,實(shí)現(xiàn)深拷貝抖格。
jQuery的extend可以深拷貝也可以淺拷貝
需要注意的是,如果對象比較大雹拄,層級也比較多,深復(fù)制會帶來性能上的問題滓玖。在遇到需要采用深復(fù)制的場景時,可以考慮有沒有其他替代的方案翩肌。在實(shí)際的應(yīng)用場景中,也是淺復(fù)制更為常用摧阅。