介绍
什么是深copy?意思就是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三以后缺胳膊少腿还是李四以后挂掉了,都不会影响另外一个人。
在js中,深copy一个对象,不论源对象或者拷贝对象改变,都不会对对象造成影响,举个js的栗子:
//我们定义了一个张三,然后又用deepCopy基于张三深拷贝了一个名字为李四的人。
var people1 = {name: '张三', age: 20, die: false, hobbies: ['旅游', '打篮球']};
var people2 = deepCopy(people1);
people2.name = '李四';
//打印people1和people2的name
console.log('people1:', people1.name, 'people2:', people2.name); //people1: 张三 people2: 李四
//我们再修改people2的兴趣爱好(hobbies)
people2.hobbies[1] = '看书';
console.log('李四的爱好是:', people2.hobbies); //李四的爱好是:["旅游", "看书"]
console.log('张三的爱好是:', people1.hobbies); //张三的爱好是:["旅游", "打篮球"]
复制代码
从上面的代码运行过程和结果我们看到,用深拷贝方法拷贝的新对象和源对象是互相不影响的。
目的
编写一个能够深copy数组和对象的js函数方法
代码
function deepCopy(obj) {
var newObj;
if(typeof obj === 'object'){
newObj = obj.constructor === Array ? [] : {};
for(var key in obj){
if(typeof obj[key] === 'object'){
newObj[key] = deepCopy(obj[key]);
}else{
newObj[key] = obj[key];
}
}
}else{
newObj = obj;
}
return newObj;
}
复制代码
讲解
上面代码中deepCopy函数的实现过程中,可以看到用到了函数递归。这里用函数递归是为了解决对象中的属性为数组或者对象时,深层拷贝的数组||对象属性。还有一个判断数组和对象的方法,我这里用的是 obj.constructor === Array ? [] : {}
,因为数组也属于对象,所以用typeof无法区分数组和对象。当然还有很多种其他的区分数组和对象的方法了,大家可以在编写自己的deepCopy方法的时候使用。
说下浅复制和深复制的区别:
浅复制:只会将对象的各个属性进行依次复制,并不会进行递归复制,而js存储对象都是存地址的,所以浅复制会导致源对象的对象||数组属性和拷贝对象的对象||数组属性 指向同一块内存地址;会导致引用。
深复制:它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。这就不会存在属性指向同一个对象||数组的问题。