深浅拷贝出现的主要原因在于js对于基本数据类型和引用数据类型的处理不同。复制基本类型时,是复制它的值,一个新的对象和内存空间;而引用类型只是操作它的引用,复制的是指向内存空间的指针,改变其中一个会影响另外一个。
浅拷贝
如果我们复制的对象中没有引用数据类型,就可以使用浅拷贝,实现方法是遍历并复制,返回一个新的对象。
//定义一个简单对象,没有引用类型
var obj={
name:'zs',
age:22
}
//定义一个浅拷贝的函数
function shallowCopy(obj){
//定义一个新对象
result={};
//遍历源对象,并复制给新对象
for(key in obj){
if(obj.hasOwnProperty(key)){
result[key]=obj[key];
}
}
return result;
}
shallowCopy(obj);
//测试,分别改变两个对象的属性,互相不干扰,说明复制成功
obj.name='ls';
result.name='ww';
console.log(obj.name,result.name);//ls,ww
深拷贝
上面的浅拷贝只是拷贝了对象中的第一层,如果对象不止一层,上面的浅拷贝就不对了。
//定义一个对象中还有一个对象的
var obj={
name:'zs',
age:22,
concat:{
num:122
}
}
//定义一个浅拷贝的函数
function shallowCopy(obj){
//定义一个新对象
result={};
//遍历源对象,并复制给新对象
for(key in obj){
if(obj.hasOwnProperty(key)){
result[key]=obj[key];
}
}
return result;
}
shallowCopy(obj);
//测试,当改变对象中的对象的属性时,此时复制就是对象的引用,其中一个改变会影响另一个的值
obj.concat.num=111;
console.log(result.concat.num);//111
如图,对象中的对象,浅拷贝只是拷贝了它的引用,所以当我们遍历对象时,要判断是否遍历到了对象,如果是就进行深层遍历,这就用到了递归操作。
1、利用递归操作完成深拷贝
//定义一个对象中还有一个对象的
var obj={
name:'zs',
age:22,
concat:{
num:122
}
}
var result={};
//定义一个深拷贝的函数
function deepCopy(obj){
for(key in obj){
//判断遍历时是否有对象,有则递归深层遍历
if(obj[key]&&typeof obj[key]==='object'){
result[key]=deepCopy(obj[key]);
}else{
result[key]=obj[key];
}
}
return result;
}
deepCopy(obj);
//测试,当改变对象中对象的属性时,拷贝后的属性并未改变,说明深拷贝成功
obj.concat.num=111;
console.log(result.concat.num);//122
2、当深拷贝的对象中没有函数时,也可以用JSON的解析反解析得到深拷贝的对象
//定义一个对象中还有一个对象的
var obj={
name:'zs',
age:22,
concat:{
num:122
}
}
//定义一个深拷贝的函数
function deepCopy(obj){
//JSON解析反解析也可以得到深拷贝对象
result=JSON.parse(JSON.stringify(obj));
return result;
}
deepCopy(obj);
//测试,当改变对象中对象的属性时,拷贝后的属性并未改变,说明深拷贝成功
obj.concat.num=111;
console.log(result.concat.num);//122