怎么使用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 相关文章推荐
JQuery 学习笔记 选择器之三
Jul 23 Javascript
jquery中获取元素的几种方式小结
Jul 05 Javascript
extjs每个组件要设置唯一的ID否则会出错
Jun 15 Javascript
javascript中的__defineGetter__和__defineSetter__介绍
Aug 15 Javascript
jQuery实用技巧必备(上)
Nov 02 Javascript
浅谈javascript的call()、apply()、bind()的用法
Feb 21 Javascript
jQuery简单实现中间浮窗效果
Sep 04 Javascript
jQuery扩展_动力节点Java学院整理
Jul 05 jQuery
vue axios请求频繁时取消上一次请求的方法
Nov 10 Javascript
vue实现pdf文档在线预览功能
Nov 26 Javascript
vue-quill-editor插入图片路径太长问题解决方法
Jan 08 Vue.js
Vue自定义铃声提示音组件的实现
Jan 22 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不用内置函数对数组排序的两个算法代码
2010/02/08 PHP
php 计划任务 检测用户连接状态
2012/03/29 PHP
PHP获取文件扩展名的方法实例总结
2017/06/10 PHP
actionscript与javascript的区别
2011/05/25 Javascript
基于jQuery的获取标签名的代码
2012/07/16 Javascript
javascript动态加载二
2012/08/22 Javascript
jquery easyui 结合jsp简单展现table数据示例
2014/04/18 Javascript
IE6浏览器中window.location.href无效的解决方法
2014/11/20 Javascript
javascript内置对象操作详解
2015/02/04 Javascript
jquery代码实现多选、不同分享功能
2015/07/31 Javascript
jQuery实现弹幕效果
2017/02/17 Javascript
TypeScript入门-接口
2017/03/30 Javascript
Node.js成为Web应用开发最佳选择的原因
2018/02/05 Javascript
vue的mixins属性详解
2018/03/14 Javascript
vue构建动态表单的方法示例
2018/09/22 Javascript
Vue 使用beforeEach实现登录状态检查功能
2019/10/31 Javascript
JS图片预加载三种实现方法解析
2020/05/08 Javascript
React实现阿里云OSS上传文件的示例
2020/08/10 Javascript
[02:08]2014DOTA2国际邀请赛 430专访:力争取得小组前二
2014/07/11 DOTA
python爬虫_自动获取seebug的poc实例
2017/08/05 Python
Python读取excel中的图片完美解决方法
2018/07/27 Python
Python实现html转换为pdf报告(生成pdf报告)功能示例
2019/05/04 Python
浅谈matplotlib.pyplot与axes的关系
2020/03/06 Python
在python中求分布函数相关的包实例
2020/04/15 Python
运行Python编写的程序方法实例
2020/10/21 Python
Pycharm安装Qt Design快捷工具的详细教程
2020/11/18 Python
详解CSS3中@media的实际使用
2015/08/04 HTML / CSS
天美时手表加拿大官网:Timex加拿大
2016/09/01 全球购物
印尼第一大家居、生活和家具电子商务:Ruparupa
2019/11/25 全球购物
编写一个类体现构造,公有,私有方法,静态,私有变量
2013/08/10 面试题
亲子拓展活动方案
2014/02/20 职场文书
战略合作意向书范本
2014/04/01 职场文书
给小学生的新年寄语
2014/04/04 职场文书
环保倡议书100字
2014/05/15 职场文书
电子商务专业应届生求职信
2014/05/28 职场文书
青年标兵事迹材料
2014/08/16 职场文书