原生JS中对象的深浅拷贝
在使用原生JS时,我们有时候会遇到要对对象进行拷贝的情况,而对象是基于堆存储的,不能直接进行赋值操作,不然新对象操作的也是旧对象的地址,引出不必要的麻烦,所以我们需要对对象进行拷贝来重新操作。而拷贝时也分为深拷贝和浅拷贝,他们的不同就是是否对对象里面的对象再进行拷贝,这里提供两种原生的方法供大家参考:
第一种:
function extend(o1,deep){
var obj = {};
if(o1 instanceof Array){
obj = [];
}
for(var key in o1){
var value = o1[key];
//判断是深拷贝还是浅拷贝,浅拷贝的话直接赋值,深拷贝的话判断是否是 引用类型并且不是null
obj[key] = (!!deep && typeof value === "object" && value !== null) ? extend(value,deep) : value;
}
return obj;
}
var obj1 = {
a : 1,
b : ["a",{
c : ["x"]
}]
}
var obj2 = extend(obj1,true);
obj2.b[1].c.push("y");
console.log("obj1:");
console.log(obj1);
console.log("obj2:");
console.log(obj2);
打印结果如下:
可以看到我们对新对象中的c对象进行操作时不会去改变旧对象中的数据,这种方法中的extend第一个参数是要拷贝的对象,第二个是可传可不传的boolean值,表示是否进行深拷贝,默认是false。
第二种:
var obj3 = {
a : 1,
b : ["a",{
c : ["x"]
}]
}
var obj4 = JSON.parse(JSON.stringify(obj3));
obj4.b[1].c.push("y");
obj4.b[1].c.push("z");
console.log("obj3:");
console.log(obj3);
console.log("obj4:");
console.log(obj4);
打印结果如下:
可以看到我们对新对象中的c对象进行操作时不会去改变旧对象中的数据,这种方法的原理是用JSON提供的序列化和反序列化来实现的,这种方法不支持里面有函数的情况。