JS中的对象复制分为两种情况:深拷贝和浅拷贝。
深拷贝和浅拷贝的区别在于对数组和对象的拷贝,对它们拷贝时浅拷贝只是拷贝引用地址,它们引用的是同一个数组或对象,所以对其进行修改时会互相影响;而深拷贝则是拷贝了整个的数组或对象,两个地址指针指向的是不同的数组或对象,这样修改互不影响。
var myObject={
a:2,
b:{c:1}
};
- 浅拷贝的实现
- Object.keys()遍历对象属性
对于上面这个对象myObject来说,要实现浅拷贝,可以遍历对象中的属性,然后将其值存入。
var keys=Object.keys(myObject);
var newObj2={};
for(var i=0;i<keys.length;i++){
newObj2[keys[i]]=myObject[keys[i]]
}
Object.keys方法可以遍历对象中的属性,并返回属性名的数组,通过对数组进行遍历,从而将其值存入新的对象中。
- ES6的Object.assign()方法
ES6中有一个方法是根据上述遍历方法得来的,可以直接调用:assign
var newObj1 = Object.assign({},myObject);
验证:
newObj1.a=4;
newObj2.a=3;
console.log(myObject.a,newObj1.a,newObj2.a);//2 4 3
newObj1.b.c=4;
console.log(myObject.b,newObj1.b,newObj2.b);//{ c: 4 } { c: 4 } { c: 4 }
通过更改上述对象中的a属性的值,可以看到,对象之间互不影响,因为该值并不是对象,所以是复制的值,直接更改。但是如果更改属性b的值,则会相互影响,因为他们引用的是同一个值。
- jQuery中的extend方法
JS中的extend()方法可以实现深拷贝和浅拷贝,通过里面的参数true,false决定。
- 深拷贝的实现
- JSON方式
先把对象转化为JSON字符串,然后再解析成对象的形式:
var newObjDeep2=JSON.parse(JSON.stringify(myObject));
验证:
myObject.b.c=4;
console.log(myObject,newObjDeep2);//{ a: 2, b: { c: 4 } } { a: 2, b: { c: 1 } }
- 递归实现
function deepCopy(obj){
var newObj;
if(typeof obj !== 'object'){
return obj;
}
if(obj instanceof Array){
newObj=[];
}else {
newObj={}
}
for(var key in obj){
if(typeof obj[key] !== "object"){
newObj[key]=obj[key];
}else{
newObj[key]=deepCopy(obj[key])
}
}
return newObj;
}
对于一个对象,先判断其数据类型是否为数组,如果是,则写为[]形式,不是,则为{}形式,之后再对里面的属性名进行遍历,判断其属性值是否为对象,如果是,则继续上述操作(即递归),如果不是,则将其值直接复制给新对象中相应的属性。
验证:
var newObjDeep1=deepCopy(myObject);
myObject.b.c=4;
console.log(myObject,newObjDeep1);//{ a: 2, b: { c: 4 } } { a: 2, b: { c: 1 } }
- 上述浅拷贝中的jQuery中的extend方法