数组的浅拷贝
我们知道数组的一些方法,比如slice,concat返回一个新数组的特性来实现拷贝
1 | var oldArr = ['old','a',true]; |
但是如果数组中嵌套了数组或者对象,看看结果如何:1
2
3
4
5
6var oldArr = [{name:'xiaojie'},['old']];
var newArr = oldArr.concat();
newArr[0].name = 'xiaobao';
newArr[1][0] = 'new';
console.log(oldArr);//[{name:'xiaobao'},['new']]
console.log(newArr);//[{name:'xiaobao'},['new']]
可以发现,改变了newArr的值,oldArr的值也跟着改变。
当数组元素是基本类型的时候,新旧数组的值互不影响,当数组元素为Object类型的时候,改变新数组的值会影响就旧数组的值。
我们把复制引用对象的拷贝方法称为浅拷贝,与之对应的就是深拷贝,深拷贝就是完全的拷贝一个对象,即使嵌套对象两者也互相分离,修改一个对象的属性,也不会影响另一个
数组的深拷贝
介绍一个简单粗暴的深拷贝方法,不仅适用于数组,还适用于对象:JSON.parse(JSON.stringify(oldArr))。1
2
3
4
5
6
7var oldArr = [{name:'xiaojie'},['old'],'old',true];
var newArr = JSON.parse(JSON.stringify(oldArr));
newArr[0].name='bao';
newArr[1][0]='new';
newArr[2]='new';
console.log(oldArr);// [{name:'xiaojie'},['old'],'old',true]
console.log(newArr);// [{name:'bao'},['new'],'new',true]
PS:方法JSON.parse(JSON.tostringify(arr))不能拷贝函数
深拷贝的实现
实现原理:试想一下,我们先拷贝最外层的基础数据类型,遇到引用类型时,在循环拷贝引用类型里面的基础类型,就可以实现深拷贝,代码如下:
1 | function deepAssign(obj){ |
ES6新增的Object.assign()
用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。来看看Object.assign()是深拷贝还是浅拷贝
1 | var oldObj={ |
由此可见Object.assign()也是浅拷贝。如果对象属性是基本类型,则互不影响,如果对象属性也是对象,则是复制的对象的应用