当前位置: 首页 > news >正文

js深复制一个数组

Array是引用类型,如果用arrA=arrB简单的把一个数组赋值,并没有创造出一个新数组,arrA和arrB其实指向的还是同一个地址,改变一个另一个也会随之改变,很明显这并不是我们想要的。
比如:

  let arr = [1, 2, 3];
  let newArr = arr;
  arr.push(4);
  console.log(newArr1);  // [1, 2, 3, 4]

若我们改变了一个数组的值,但是另一个数组的值不想发生改变,可以使用以下的方法,注:仅适用于数组的浅复制。数组中元素不包含数组类型和对象类型。

1.使用concat方法:

var arr = [1, 2, 3];
var newArr = arr.concat();
arr.push(4)
console.log(newArr);//[1,2,3]
console.log(arr);//[1,2,3,4]

2.slice(start,end)方法。(我经常使用这个方法对数组进行复制)
1.从start开始截取到end但是不包括end;
2.返回值为截取的元素集合;

  var arr = [1, 2, 3];
  var newArr = arr.slice();
  arr[0] = 10;
  console.log(arr);// [10, 2, 3]
  console.log(newArr);// [1, 2, 3]

3.使用扩展运算符

  var arr = [1, 2, 3];
  var [ ...newArr ] = arr;
  arr[0] = 10;
  console.log(arr); // [10, 2, 3]
  console.log(newArr);// [1, 2, 3]

4.Object.assign()

 var arr = [1, 2, 3];
 var newArr = Object.assign([], arr);
 arr[0] = 10;
 console.log(arr);// [10, 2, 3]
 console.log(newArr);// [1, 2, 3]

如果数组元素是对象或者数组,上面四种方法就会只拷贝数组或者对象的引用,如果我们对其中一个数组进行修改,另一个数组也会发生变化。比如:

 var arr = [ { a: 1 }, [ 1, 2 ], 3 ];
  let newArr = arr.concat();
  arr[0].a = 2;
  console.log(arr); // [ { a: 2 }, [ 1, 2 ], 3 ]
  console.log(newArr);// [ { a: 2 }, [ 1, 2 ], 3 ] 另一数组的值也会发生改变

下面是深复制(可以完全拷贝一个数组,即使嵌套了对象或者数组,两者也不会互相影响)
方法一:JSON.parse(JSON.stringify(arr))

  var arr = [ { a: 1 }, [ 1, 2 ], 3 ];
  let newArr = JSON.parse(JSON.stringify(arr));
  arr[0].a = 2;
  console.log(arr); // [ { a: 2 }, [ 1, 2 ], 3 ]
  console.log(newArr);// [ { a: 1 }, [ 1, 2 ], 3 ] 新数组的值不会发生改变
  

但是该方法是有一定的缺陷的,比如:

循环应用的对象
会忽略undefined
不能序列化函数
会忽略symbol

通用方法,若元素是对象或者数组,继续调用深拷贝

 var deepCopy = function(obj) {
    // 判断是否是对象
    if (typeof obj !== 'object') return;
    // 判断obj类型,根据类型新建一个对象或者数组
    var newObj = obj instanceof Array ? [] : {}
    // 遍历对象,进行赋值
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        let val = obj[key];
        // 判断属性值的类型,如果是对象,递归调用deepCopy
        newObj[key] = typeof val === 'object' ? deepCopy(val) : val
      }
    }
    return newObj
  }

或者利用lodash中的深度copy

import cloneDeep from 'lodash/cloneDeep'
let newArr= clobeDeep(arr);

相关文章:

  • 03.3线性回归的简洁实现
  • 基于51单片机简易十字路口交通灯_5s全黄闪烁
  • 高并发、高性能、高可用的理解及处理方式
  • Faster R-CNN
  • AndroidSDK开发6我用kotlin写了一个简单sdk
  • Linux设置定时任务
  • 研发效能的逻辑:填补软工鸿沟
  • 如何为 Docker 容器设置内存限制
  • mysql的索引分类B+和hash详解
  • Kafka陌陌案例,220903,,
  • Vue 使用原生 js 实现锚点定位到指定位置
  • 64. 最小路径和 java解决
  • 【mia】rtc_Push和player拉取
  • GDScript进行HTTP请求以及session问题
  • Python + Selenium + Chrome Driver 自动化点击+评论+刷弹幕(仅供学习)
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • Koa2 之文件上传下载
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • python大佬养成计划----difflib模块
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • tab.js分享及浏览器兼容性问题汇总
  • 从输入URL到页面加载发生了什么
  • 分布式事物理论与实践
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 说说动画卡顿的解决方案
  • 微服务核心架构梳理
  • 我从编程教室毕业
  • 项目实战-Api的解决方案
  • 携程小程序初体验
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • #include
  • #单片机(TB6600驱动42步进电机)
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (¥1011)-(一千零一拾一元整)输出
  • (10)ATF MMU转换表
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (利用IDEA+Maven)定制属于自己的jar包
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (十)c52学习之旅-定时器实验
  • (一)VirtualBox安装增强功能
  • *1 计算机基础和操作系统基础及几大协议
  • . Flume面试题
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .net Application的目录
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .net6 webapi log4net完整配置使用流程
  • .NET建议使用的大小写命名原则
  • /etc/sudoer文件配置简析
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • [BT]BUUCTF刷题第4天(3.22)
  • [bzoj4010][HNOI2015]菜肴制作_贪心_拓扑排序
  • [CF494C]Helping People
  • [datastore@cyberfear.com].Elbie、[thekeyishere@cock.li].Elbie勒索病毒数据怎么处理|数据解密恢复