所谓浅拷贝,就是副本和原来的对象共享一个对象。
示例:
var arr=[1,2,3,4];
var arr1=arr;
实际上arr和arr1指向的是同一个堆内存地址,当对arr1操作时,arr的值也会发生变化。
如:
arr1.push(5);
那么arr和arr1数组的元素都是[1,2,3,4,5]。
提出问题:有什么解决方案呢?
使用JSON.stringify()方法辅助
var arr1=JSON.parse(JSON.stringify(arr));
那么arr1和arr实际指向的内存就是不一样了,arr和arr1的操作就不会互相影响了。
对于简单数组
还可以使用:for循环(在循环中定义一个空数组,循环结束后返回)、slice()、contact()、Array.from()方法。在ES6中,还可以使用扩展运算符。
对于简单对象的话
可以使用for循环,因为如果对象里有数组的话,副本和原对象对于数组还是会互相影响的。
var obj={
name:'袁文军',
age:26,
habbits:['编程','看书']
};
function cloneObj(a) {
var result={};
for (var key in obj){
result[key]=obj[key];
}
return result;
}
var obj1=cloneObj(obj);
obj1.habbits.push('开车');
obj1.name='华为';
console.log(obj);
console.log(obj1);
在以上代码中,name和age是不会互相影响的,但是habbits是会互相影响的
接下来,我们使用JSON来处理,看一下。
var obj={
name:'袁文军',
age:26,
habbits:['编程','看书']
};
var obj1=JSON.parse(JSON.stringify(obj));
obj1.habbits.push('开车');
obj1.name='华为';
console.log(obj);
console.log(obj1);
从输出结果来看,两者结果显然不会受影响。但是此类方法,会忽略函数对象和原型对象。
在ES6中,使用Object.assign()克隆对象,对象中的数组还是会相互影响的,
接下来总结一个拷贝对象和数组的方法,无论是复杂对象和复杂数组。
var obj={
name:'袁文军',
age:26,
habbits:['编程','看书'],
addres:{city:'吉安',xiancheng:['遂川','安福','井冈山']}
};
var obj1=clone(obj);
function clone(a) {
var result=(a instanceof Object)?{}:[];
if(a){
for(var key in a){
if(a.hasOwnProperty(key)){ // 用来忽略继承属性
if(a[key]&&Array.isArray(a[key])){ // 不加此判断,会出现数组变为伪数组的情况
result[key]=(a[key]).slice();
continue;
}if(a[key]&&typeof a[key] ==='object'){
result[key]=clone(a[key]);
}
else{
result[key]=a[key];
}
}
}
return result;
}
}
obj1.habbits.push('妹子');
console.log(obj);
console.log(obj1);