浅拷贝
数组和对象作为JS的引用类型,直接使用赋值“=”的话,会把源数组、对象的地址赋值给新的数组、对象,并没有实现数组的数据拷贝,这种方式实现的就是浅拷贝。赋值给另一个变量时,实际上是把另一个变量指向了与之相同的地址,当我们改变其中一个时,实际上改变了堆内存中的存储内容,相应的所有指向该地址的数组都发生了变化
深拷贝
深拷贝是重新分配新的存储空间,两个对象对应不同的地址,修改其中一个值,不会影响另外一个对象的值
有时候我们希望得到的新的对象或数组,不受原来的对象或数组影响,所以就需要深拷贝
数组的深拷贝
使用slice和concat方法,以及ES6的[…arr],循环数组
- let newarr = […arr]
- concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本
let newarr = arr.concat() - array.slice(start, [end])忽略那么 slice 方法将一直复制到 array的结尾
let arr = arr.slice(0) - 循环遍历
var arr1 = [1,2,3];//原来数组
var arr2 = [];//新数组
function deepCopy(arry1, arry2){
var length = arry1.length;
for(var i = 0;i<length;i++){
arry2[i] = arry1[i];
}
}
slice,concat方法,以及ES6的[…arr]的局限性:
如果数组里面的值是数组对象的话,那么就会发现,深拷贝不起作用
由于数组内部属性值为引用对象,因此使用slice和concat对对象数组的拷贝,整个拷贝还是浅拷贝,拷贝之后数组各个值的指针还是指向相同的存储地址。
因此,slice和concat这两个方法,仅适用于对不包含引用对象的一维数组的深拷贝
对于数组对象的深拷贝,可以采用转换成字符串的方式
let newarr = JSON.parse(JSON.stringify(arr))
这种方式可以解决相当多一部分的赋值问题,但是一些特殊属性除外(undefined/function)
对象的深拷贝
对象的深拷贝ES6的{…obj},Object.assign({},obj)
- let newobj = {…obj }
- let newobj = Object.assign({}, obj )
综上
let newarr = JSON.parse(JSON.stringify(arr))
可以解决大部分深拷贝的问题