数组和对象的浅拷贝和深拷贝

时间:2021-02-17 19:48:22

在jsvaScript中,简单值是通过直复制来进行赋值传递的,而引用类型是通过引用赋值来进行复制传递的。

var a = 2;
var b = a;
b
= 3;
console.log(a)
//2
console.log(b) //3


var arr1 = [1,2,3];
var arr2
= arr1;
arr2.push(
4);
console.log(arr1);
//[1,2,3,4]
console.log(arr2); //[1,2,3,4]

第一种情况就是简单值得复制传递,a和b分别在两个内存中,b=a知识吧a的值复制给b,改变b的值不会影响a的值。

第二种情况是引用类型的复制,arr2 = arr1是将arr1的地址复制给arr2,两个数组指向同一片内存区域,所以改变arr2的值也会改变arr1的值。是数组的浅拷贝。

下面来看看什么是数组的深拷贝

var a = [1,2,3];
var b = a.slice(0);
var c = a.concat();
b.push(
4);
c.push(
5);

console.log(a);
//[1,2,3]
console.log(b); //[1,2,3,4]
console.log(c); //[1,2,3,5]

对象的浅拷贝

function easyClone(Obj) {
var objNew = {};
for ( var i in Obj) {
objNew[i]
= Obj[i];
}
return objNew;
}

其实就是将每个原对象的属性和值复制到新对象上去,当然我们也可以使用Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象,同时Object.assign() 也是浅拷贝。

浅拷贝因为没有递归循环检查对象的每个值是否是对象,而是直接进行了赋值,所以如果某个值是对象的时候就会出现问题,所以在一般情况下我们需要用深拷贝来进行备份。

对象的深拷贝

最简单的深拷贝

var b = JSON.parse(JSON.stringify(a))

但是这种深拷贝有一定的局限性,第一:无法复制函数,第二:原形链没了,对象就是object,所属的类没了。

其实简单的深拷贝只需要我们递归调用浅拷贝就可以了:

function deepCopy(obj) {
  
var objNew = objNew || {};
  
for (var i in obj) {
    
if (typeof p[i] === 'object') {
      objNew[i]
= (p[i].constructor === Array) ? [] : {};
      deepCopy(obj[i], objNew[i]);
    }
else {
       objNew[i]
= obj[i];
    }
  }
  
return objNew;
}