怎么使用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 相关文章推荐
Javascript 获取LI里的内容
Dec 17 Javascript
JavaScript 比较时间大小的代码
Apr 24 Javascript
自己写的Javascript计算时间差函数
Oct 28 Javascript
Node.js的包详细介绍
Jan 14 Javascript
使用AngularJS对路由进行安全性处理的方法
Jun 18 Javascript
全面理解JavaScript中的闭包
May 12 Javascript
vue2.0获取自定义属性的值
Mar 28 Javascript
vue.js整合vux中的上拉加载下拉刷新实例教程
Jan 09 Javascript
webpack4.x开发环境配置详解
Aug 04 Javascript
使用element-ui table expand展开行实现手风琴效果
Mar 15 Javascript
js实现小星星游戏
Mar 23 Javascript
Nuxt的动态路由和参数校验操作
Nov 09 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调用mysql存储过程
2007/02/14 PHP
PHP extract 将数组拆分成多个变量的函数
2010/06/30 PHP
PHP 函数学习简单小结
2010/07/08 PHP
PHP中通过fopen()函数访问远程文件示例
2014/11/18 PHP
php猜单词游戏
2015/09/29 PHP
PHP编写登录验证码功能 附调用方法
2016/05/19 PHP
Laravel 已登陆用户再次查看登陆页面的自动跳转设置方法
2019/09/30 PHP
Javascript读取cookie函数代码
2010/10/16 Javascript
借助script进行Http跨域请求:JSONP实现原理及代码
2013/03/19 Javascript
jQuery控制TR显示隐藏的几种方法
2014/06/18 Javascript
input输入框鼠标焦点提示信息
2015/03/17 Javascript
jQuery实现鼠标经过提示信息的地图热点效果
2015/04/26 Javascript
BootStrap创建响应式导航条实例代码
2016/05/31 Javascript
jquery validate 实现动态增加/删除验证规则操作示例
2019/10/28 jQuery
vue实现评价星星功能
2020/06/30 Javascript
[06:04]DOTA2国际邀请赛纪录片:Just For LGD
2013/08/11 DOTA
[22:20]初生之犊-TI4第5名LGD战队纪录片
2014/08/13 DOTA
Python将图片转换为字符画的方法
2020/06/16 Python
python删除字符串中指定字符的方法
2018/08/13 Python
Python minidom模块用法示例【DOM写入和解析XML】
2019/03/25 Python
Python 根据日志级别打印不同颜色的日志的方法示例
2019/08/08 Python
Python内置加密模块用法解析
2019/11/25 Python
Python3连接Mysql8.0遇到的问题及处理步骤
2020/02/17 Python
Python3.7.0 Shell添加清屏快捷键的实现示例
2020/03/23 Python
使用Python实现微信拍一拍功能的思路代码
2020/07/09 Python
Python jieba结巴分词原理及用法解析
2020/11/05 Python
aec加密 php_php aes加密解密类(兼容php5、php7)
2021/03/14 PHP
CSS3 3D旋转rotate效果实例介绍
2016/05/03 HTML / CSS
CSS3实现曲线阴影和翘边阴影
2016/05/03 HTML / CSS
HTML5注册表单的自动聚焦与占位文本示例代码
2013/07/19 HTML / CSS
罗技美国官网:Logitech美国
2020/01/22 全球购物
Made in Design意大利:现代家具、名家灯具和装饰
2020/10/27 全球购物
保安自我鉴定范文
2013/12/08 职场文书
经济贸易系求职信
2014/08/04 职场文书
2016春季小学开学寄语
2015/12/03 职场文书
MYSQL 运算符总结
2021/11/11 MySQL