怎么使用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 相关文章推荐
不同浏览器对回车提交表单的处理办法
Feb 13 Javascript
js实现一个省市区三级联动选择框代码分享
Mar 06 Javascript
JS高级调试技巧:捕获和分析 JavaScript Error详解
Mar 16 Javascript
JavaScript用Number方法实现string转int
May 13 Javascript
jQuery文件上传插件Uploadify使用指南
Jun 05 Javascript
AngularJS表格样式简单设置方法示例
Mar 03 Javascript
spirngmvc js传递复杂json参数到controller的实例
Mar 29 Javascript
Bootstrap模态对话框中显示动态内容的方法
Aug 10 Javascript
微信公众平台获取access_token的方法步骤
Mar 29 Javascript
javascript数据类型中的一些小知识点(推荐)
Apr 18 Javascript
功能完善的小程序日历组件的实现
Mar 31 Javascript
jQuery实现动态向上滚动
Dec 21 jQuery
微信小程序如何使用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/05/16 PHP
浅析十款PHP开发框架的对比
2013/07/05 PHP
PHP实现的简单留言板功能示例【基于thinkPHP框架】
2018/12/07 PHP
PHP7实现和CryptoJS的AES加密方式互通示例【AES-128-ECB加密】
2019/06/08 PHP
PHP实现笛卡尔积算法的实例讲解
2019/12/22 PHP
一个无限级XML绑定跨框架菜单(For IE)
2007/01/27 Javascript
JS格式化数字金额用逗号隔开保留两位小数
2013/10/18 Javascript
简单的Jquery遮罩层代码实例
2013/11/14 Javascript
优化Node.js Web应用运行速度的10个技巧
2014/09/03 Javascript
jQuery中 attr() 方法使用小结
2015/05/03 Javascript
Jquery ajax请求导出Excel表格的实现代码
2016/06/08 Javascript
jquery实现界面无刷新加载登陆注册
2016/07/30 Javascript
AngularJS 单元测试(一)详解
2016/09/21 Javascript
Spring shiro + bootstrap + jquery.validate 实现登录、注册功能
2017/06/02 jQuery
使用 Javascript 实现浏览器推送提醒功能的示例
2017/11/03 Javascript
浅谈Vue响应式(数组变异方法)
2018/05/07 Javascript
vue路由守卫,限制前端页面访问权限的例子
2019/11/11 Javascript
微信小程序抽奖组件的使用步骤
2021/01/11 Javascript
python2与python3的print及字符串格式化小结
2018/11/30 Python
完美解决Python matplotlib绘图时汉字显示不正常的问题
2019/01/29 Python
Python reversed函数及使用方法解析
2020/03/17 Python
Python3爬虫中识别图形验证码的实例讲解
2020/07/30 Python
Python‘==‘ 及 ‘is‘相关原理解析
2020/09/05 Python
德国PC硬件网站:CASEKING
2016/10/20 全球购物
Expedia加拿大官方网站:加拿大最大的在线旅游提供商
2017/12/31 全球购物
ghd法国官方网站:英国最受欢迎的美发工具品牌
2019/04/18 全球购物
ColourPop美国官网:卡拉泡泡,洛杉矶彩妆品牌
2019/04/28 全球购物
个人自我鉴定怎么写
2013/10/28 职场文书
中专毕业生自荐信
2013/11/16 职场文书
小学新学期寄语
2014/04/02 职场文书
学习雷锋演讲稿
2014/05/10 职场文书
公司合作协议范文
2014/10/01 职场文书
2015年学校图书室工作总结
2015/05/19 职场文书
公司新员工欢迎词
2015/09/30 职场文书
Django使用echarts进行可视化展示的实践
2021/06/10 Python
十大最帅动漫男主 碓冰拓海上榜,第一是《灌篮高手》男主角
2022/03/18 日漫