js中深复制和浅复制
今天忽然想到了这个问题,总结一下js中有哪些复制对象的方法。先得明白什么是深复制,什么是浅复制,举个栗子:
var arr = [[1,2],3,4];
var brr = arr.slice();
//这时候brr是arr的浅复制
console.log(brr);
为啥呢?再试试这样:
brr[0][1] = 5;
console.log(arr) // result is [[1,5],3,4];
因为arr[0]是一个数组,而brr[0]只是引用了这个数组;
所以深复制也就很好理解了,当改变任何brr的值都不会影响arr,那么该怎么实现呢?实现的方法有好几种,下面一一列举。
1.最熟悉的方法可能就是jQuery中的方法 $.extend()
,看看jQuery官方的例子:
//浅复制
var object1 = {
apple: 0,
banana: { weight: 52, price: 100 },
cherry: 97
};
var object2 = {
banana: { price: 200 },
durian: 100
};
// Merge object2 into object1
$.extend( object1, object2 );
//result is {"apple":0,"banana":{"price":200},"cherry":97,"durian":100}
//深复制
$.extend( true, object1, object2 );
//result is {"apple":0,"banana":{"weight":52,"price":200},"cherry":97,"durian":100}
深复制会递归的复制
2.原生的js实现
function clone(obj){
//这一行很重要,判断obj是否基本类型 null,undefined,string,number,boolean,如果是直接返回,因为没法再继续循环了。
if(obj == null || typeof obj !=='object') return obj
if(obj instanceof Array){
var arr = [];
for(var i=0, len=obj.length; i<len; i++){
//这一步就是深度复制的magic所在了
arr[i] = clone(obj[i]);
}
return arr;
}
if(obj instanceof Object){
//实例化obj的构造函数,得到和obj一样的prototype.
var tem_obj = obj.constructor();
for(attr in obj){
if(obj.hasOwnProperty(attr)){
//把obj实例的自有属性复制到temobj
tem_obj[attr] = clone(obj[attr]);
}
}
return tem_obj
}
}
var arr = [[1,2],3,4];
var brr = clone(arr);
brr[0][1] = 5;
console.log(arr) //[[1,2],3,4]
that’s it.
3.es6中的Object.assign
,实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
详细的参考这里
Object.assign(target, source1, source2);
var obj1 = {a: {b: 1}};
var obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2