怎么使用javascript深度拷贝一个数组


Posted in Javascript onJune 06, 2019

有两种数组拷贝类型:浅拷贝 & 深拷贝。浅拷贝只会拷贝数组的第一层,剩下的会引用。如果你需要一个嵌套的数组的拷贝,那需要你去深度拷贝这个数组。深拷贝,选择JSON方法或者Lodsh库吧

const numbers = [1, [2], [3, [4]], 5];
// Using JavaScript
JSON.parse(JSON.stringify(numbers));
// Using Lodash
_.cloneDeep(objects);

数组是引用类型

为了搞清楚为什么有两种类型的拷贝,我们来深度了解一下基础知识然后解释什么是引用类型。
与原始类型(number、string)不同,数组是引用类型。这意味着当你把一个数组赋值给一个变量,你是将数组的内存地址而非数组本身赋给变量。

拷贝值类型

这里没什么大不了的,我们创建一个value的拷贝。当我们改变valueCopy的值,它不会影响原来的value值。同理,当我们改变原来的值它也不会影响拷贝后的值。很好?

let value = 3;
let valueCopy = value; // create copy
console.log(valueCopy); // 3
// Change valueCopy
valueCopy = 100
console.log(valueCopy); // 100
// ✅ Original NOT affected 
console.log(value); // 3

拷贝引用类型

好的,这里就会有点奇怪了!我们用同样的方法拷贝数组。

let array = [1,2,3];
let arrayCopy = array; // create copy
console.log(arrayCopy); // [1,2,3];
// Change 1st element of the array
arrayCopy[0] = '?';
console.log(arrayCopy); // [ '?', 2, 3 ]
// ❌Original got affected
console.log(array); // [ '?', 2, 3 ]

为什么原来的数组也受到了影响呢?好了,是因为:你拷贝的不是你拷贝的。说人话,意思就是你拷贝的只是指向数组内存空间的指针。引用类型不包含值,它们是指向内存中值的指针。

拷贝引用类型的方法

解决方法就是拷贝值而不是指针。

let array = [1,2,3];
let arrayCopy = [...array]; // create TRUE copy
console.log(arrayCopy); // [1,2,3];
// Change 1st element of the array
arrayCopy[0] = '?';
console.log(arrayCopy); // [ '?', 2, 3 ]
// ✅ Original NOT affected 
console.log(array); // [ 1, 2, 3 ]

浅 & 深 拷贝

当我使用展开扩展符号...来拷贝一个数组,我只是浅拷贝了一个数组。如果数组是嵌套或者多维的,这就不奏效了。

let nestedArray = [1, [2], 3];
let arrayCopy = [...nestedArray];
// Make some changes
arrayCopy[0] = '?'; // change shallow element
arrayCopy[1][0] = '?'; // change nested element
console.log(arrayCopy); // [ '?', [ '?' ], 3 ]
// ❌ Nested array got affected
console.log(nestedArray); // [ 1, [ '?' ], 3 ]

如上,浅拷贝首层数组表现良好,然而,更改了嵌套数组元素,原始数组也受到影响?。为了解决这个问题,就要用到深拷贝了。

let nestedArray = [1, [2], 3];
let arrayCopy = JSON.parse(JSON.stringify(nestedArray));
// Make some changes
arrayCopy[0] = '?'; // change shallow element
arrayCopy[1][0] = '?'; // change nested element
console.log(arrayCopy); // [ '?', [ '?' ], 3 ]
// ✅ Nested array NOT affected
console.log(nestedArray); // 1, [ 2 ], 3 ]

所以,这就完事了吗?要不要手写一个深拷贝引用类型的方法?

const deepClone = obj => {
const isObject = args => (typeof args === 'object' || typeof args === 'function') && typeof args !== null
if (!isObject) throw new Error('Not Reference Types')
let newObj = Array.isArray(obj) ? [...obj] : { ...obj }
Reflect.ownKeys(newObj).map(key => {
newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
})
return newObj
}

文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,

Javascript 相关文章推荐
Js日期选择自动填充到输入框(界面漂亮兼容火狐)
Aug 02 Javascript
JS+CSS设置img在DIV中只显示Img垂直居中的部分
Oct 24 Javascript
js动态添加表格数据使用insertRow和insertCell实现
May 22 Javascript
jquery动态改变div宽度和高度
Feb 09 Javascript
微信小程序 LOL 英雄介绍开发实例
Sep 30 Javascript
关于JS Lodop打印插件打印Bootstrap样式错乱问题的解决方案
Dec 23 Javascript
利用angularjs1.4制作的简易滑动门效果
Feb 28 Javascript
利用Angular+Angular-Ui实现分页(代码加简单)
Mar 10 Javascript
JavaScript原生实现观察者模式的示例
Dec 15 Javascript
vue表单数据交互提交演示教程
Nov 13 Javascript
JS遍历树层级关系实现原理解析
Aug 31 Javascript
vue css 相对路径导入问题级踩坑记录
Jun 05 Vue.js
微信小程序如何使用globalData的方法
Jun 06 #Javascript
详解微信小程序开发(项目从零开始)
Jun 06 #Javascript
vue如何自动化打包测试环境和正式环境的dist/test文件
Jun 06 #Javascript
jQuery+ajax实现批量删除功能完整示例
Jun 06 #jQuery
JS根据json数组多个字段排序及json数组常用操作
Jun 06 #Javascript
了解在JavaScript中将值转换为字符串的5种方法
Jun 06 #Javascript
Vue项目总结之webpack常规打包优化方案
Jun 06 #Javascript
You might like
用PHP制作静态网站的模板框架(一)
2006/10/09 PHP
基于PHP异步执行的常用方式详解
2013/06/03 PHP
apache中为php 设置虚拟目录
2014/12/17 PHP
php基于dom实现的图书xml格式数据示例
2017/02/03 PHP
使用PHPUnit进行单元测试并生成代码覆盖率报告的方法
2019/03/08 PHP
PHP中localeconv()函数的用法
2019/03/26 PHP
javascript下有关dom以及xml节点访问兼容问题
2007/11/26 Javascript
js实现杯子倒水问题自动求解程序
2013/03/25 Javascript
javascript标签在页面中的位置探讨
2013/04/11 Javascript
JS定义回车事件(实现代码)
2013/07/08 Javascript
showModalDialog模态对话框的使用详解以及浏览器兼容
2014/01/11 Javascript
jQuery中html()方法用法实例
2014/12/25 Javascript
JavaScript实现LI列表数据绑定的方法
2015/08/04 Javascript
纯css实现窗户玻璃雨滴逼真效果
2015/08/23 Javascript
阿里云ecs服务器中安装部署node.js的步骤
2016/10/08 Javascript
VUE element-ui 写个复用Table组件的示例代码
2017/11/18 Javascript
浅谈node.js 命令行工具(cli)
2018/05/10 Javascript
vue select选择框数据变化监听方法
2018/08/24 Javascript
nodejs微信开发之接入指南
2019/03/17 NodeJs
前端开发之便利店收银系统代码
2019/12/27 Javascript
vue实现把接口单独存放在一个文件方式
2020/08/13 Javascript
[05:31]DOTA2英雄梦之声_第08期_莉娜
2014/06/23 DOTA
[42:24]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第三场 11.27
2020/12/01 DOTA
python用来获得图片exif信息的库实例分析
2015/03/16 Python
在Python程序中操作文件之isatty()方法的使用教程
2015/05/24 Python
Python xlwt设置excel单元格字体及格式
2020/04/18 Python
python实现批量视频分帧、保存视频帧
2019/05/31 Python
详解pytorch tensor和ndarray转换相关总结
2020/09/03 Python
Hotels.com加拿大:领先的在线住宿网站
2018/10/05 全球购物
面向对象编程是如何提高软件开发水平的
2014/05/06 面试题
Java中的异常处理机制的简单原理和应用
2013/04/27 面试题
党委书记个人对照检查材料
2014/09/15 职场文书
干部作风整顿自我剖析材料和整改措施
2014/09/18 职场文书
2014年残疾人工作总结
2014/12/06 职场文书
电力安全教育培训心得体会
2016/01/11 职场文书
pytorch中的torch.nn.Conv2d()函数图文详解
2022/02/28 Python