怎么使用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 相关文章推荐
将中国标准时间转换成标准格式的代码
Mar 20 Javascript
angularJS 中$attrs方法使用指南
Feb 09 Javascript
jQuery性能优化技巧分析
Feb 20 Javascript
用JavaScript显示浏览器客户端信息的超相近教程
Jun 18 Javascript
js绘制购物车抛物线动画
Nov 18 Javascript
input获取焦点时底部菜单被顶上来问题的解决办法
Jan 24 Javascript
详解基于Bootstrap+angular的一个豆瓣电影app
Jun 26 Javascript
React props和state属性的具体使用方法
Apr 12 Javascript
js实现小星星游戏
Mar 23 Javascript
微信小程序 scroll-view的使用案例代码详解
Jun 11 Javascript
jquery实现上传图片功能
Jun 29 jQuery
JavaScript arguments.callee作用及替换方案详解
Sep 02 Javascript
微信小程序如何使用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 GD 图像处理组件的常用函数总结
2010/04/28 PHP
XAMPP安装与使用方法详细解析
2013/11/27 PHP
PHP内核学习教程之php opcode内核实现
2016/01/27 PHP
PHP框架Laravel插件Pagination实现自定义分页
2020/04/22 PHP
手把手教你自己写一个js表单验证框架的方法
2010/09/14 Javascript
jquery一般方法介绍 入门参考
2011/06/21 Javascript
js 判断js函数、变量是否存在的简单示例代码
2014/03/04 Javascript
javascript组合使用构造函数模式和原型模式实例
2015/06/04 Javascript
AngularJS整合Springmvc、Spring、Mybatis搭建开发环境
2016/02/25 Javascript
JavaScript数组方法总结分析
2016/05/06 Javascript
HTML5 实现的一个俄罗斯方块实例代码
2016/09/19 Javascript
Bootstrap3 多选和单选框(checkbox)
2016/12/29 Javascript
canvas实现弧形可拖动进度条效果
2017/05/11 Javascript
bootstrap Table插件使用demo
2017/08/07 Javascript
详解微信小程序实现WebSocket心跳重连
2018/07/31 Javascript
vue解决一个方法同时发送多个请求的问题
2018/09/25 Javascript
如何安装控制器JavaScript生成插件详解
2018/10/21 Javascript
Angular Excel 导入与导出的实现代码
2019/04/17 Javascript
jquery 遍历hash操作示例【基于ajax交互】
2019/10/12 jQuery
vue 实现走马灯效果
2019/10/28 Javascript
Vue实现点击箭头上下移动效果
2020/06/11 Javascript
Json实现传值到后台代码实例
2020/06/30 Javascript
js实现数字跳动到指定数字
2020/08/25 Javascript
[50:54]完美世界DOTA2联赛 GXR vs IO 第三场 11.07
2020/11/10 DOTA
python3制作捧腹网段子页爬虫
2017/02/12 Python
Python zip函数打包元素实例解析
2019/12/11 Python
Anconda环境下Vscode安装Python的方法详解
2020/03/29 Python
python中列表的含义及用法
2020/05/26 Python
Book Depository亚太地区:一家领先的国际图书零售商
2019/05/05 全球购物
施华洛世奇巴西官网:SWAROVSKI巴西
2019/12/03 全球购物
祖国在我心中演讲稿600字
2014/05/04 职场文书
项目经理任命书内容
2014/06/06 职场文书
2013年最新自荐信范文
2014/06/23 职场文书
甲乙双方合作协议书
2014/10/13 职场文书
员工升职自我评价
2019/03/26 职场文书
apache虚拟主机配置的三种方式(小结)
2022/07/23 Servers