关于数组、对象的深浅拷贝

浅拷贝

数组和对象作为JS的引用类型,直接使用赋值“=”的话,会把源数组、对象的地址赋值给新的数组、对象,并没有实现数组的数据拷贝,这种方式实现的就是浅拷贝。赋值给另一个变量时,实际上是把另一个变量指向了与之相同的地址,当我们改变其中一个时,实际上改变了堆内存中的存储内容,相应的所有指向该地址的数组都发生了变化

深拷贝

深拷贝是重新分配新的存储空间,两个对象对应不同的地址,修改其中一个值,不会影响另外一个对象的值

有时候我们希望得到的新的对象或数组,不受原来的对象或数组影响,所以就需要深拷贝

数组的深拷贝

使用slice和concat方法,以及ES6的[…arr],循环数组

  1. let newarr = […arr]
  2. concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本
    let newarr = arr.concat()
  3. array.slice(start, [end])忽略那么 slice 方法将一直复制到 array的结尾
    let arr = arr.slice(0)
  4. 循环遍历
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)

  1. let newobj = {…obj }
  2. let newobj = Object.assign({}, obj )

综上
let newarr = JSON.parse(JSON.stringify(arr)) 可以解决大部分深拷贝的问题

发布了137 篇原创文章 · 获赞 30 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/hani_wen/article/details/103976851
今日推荐