前端踩坑之数组拷贝
栏目: JavaScript · 发布时间: 5年前
内容简介:众所周知,在 JavaScript 中对象之间的赋值,只是拷贝对象的引用,也就是浅拷贝,不是真正意义上的拷贝,两个对象之间还会相互影响。然而,我一直忽略了一个问题,数组之间的拷贝会不会也有同样的问题呢?果不其然,当我再次用常用的 array.concat() 方法拷贝数组时,踩到坑了。当我改变一个数组里面对象属性的时候,另一个数组里的对象也跟着改变了。。。这种拷贝方法是这几种方法产生的效果是一样的。
众所周知,在 JavaScript 中对象之间的赋值,只是拷贝对象的引用,也就是浅拷贝,不是真正意义上的拷贝,两个对象之间还会相互影响。然而,我一直忽略了一个问题,数组之间的拷贝会不会也有同样的问题呢?果不其然,当我再次用常用的 array.concat() 方法拷贝数组时,踩到坑了。当我改变一个数组里面对象属性的时候,另一个数组里的对象也跟着改变了。。。
数组的拷贝方法有很多,按结果来看就是浅拷贝和深拷贝两种。
一、直接赋值
let arr2 = arr1; 复制代码
这种拷贝方法是 浅拷贝 ,数组arr1和数组arr2共用同一内存,其中一个数组改变,另一个数组也会跟着改变。
二、使用 slice(),concat(),assign() 方法
let arr2 = arr1.slice(0); let arr3 = [].concat(arr1); let arr4 = Object.assign({} , arr1); 复制代码
这几种方法产生的效果是一样的。
- 若原数组中 不存在 引用类型,修改新数组, 不会 影响到原数组的值。
- 若原数组中 存在 引用类型,修改新数组, 会 影响到原数组的值
原因是这样拷贝数组中 非引用类型 的值属于 深 拷贝, 引入类型 的值属于 浅 拷贝。
三、深拷贝方法
1. JSON复制法
let arr2 = JSON.parse(JSON.stringify(arr1)); 复制代码
但是这种方式有一定的局限性,就是数组必须遵从JSON的格式,当遇到层级较深,且序列化数组不完全符合JSON格式时,使用JSON的方式进行深拷贝就会出现问题。
所有函数及原型成员都会被有意忽略,不体现在结果中。此外,值为 undefined 的任何属性也都会被跳过。结果中最终都是值为有效 JSON 数据类型的实例属性。
2. 使用递归
function deepClone(source) { // 递归终止条件 if (!source || typeof source !== 'object') { return source; } var targetObj = source.constructor === Array ? [] : {}; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key) { if (source[key] && typeof source[key] === 'object') { targetObj[key] = deepClone(source[key]); } else { targetObj[key] = source[key]; } } } return targetObj; } 复制代码
对于 Function 类型,这里是直接复制的,任然是共享一个内存地址。因为函数更多的是完成某些功能,对函数的更改可能就是直接重新赋值,一般情况下不考虑深拷贝。 上面的深拷贝只是比较简单的实现,没有考虑很复杂的情况,比如:
- 其他引用类型:Function,Date,RegExp 的拷贝
- 对象中存在循环引用(Circular references)会导致调用栈溢出
- 通过闭包作用域来实现私有成员的这类对象不能真正的被拷贝。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 前端通关日记之优雅添加数组元素
- 前端算法题:二维数组中(每个一维数组的长度相同),左右和上下分别递增,求是否含有指定整数
- 「前端面试题系列8」数组去重(10 种浓缩版)
- 一篇文章完全掌握 JavaScript 数组操作[每日前端夜话0x87]
- C语言指针数组和数组指针
- 数组 – 如何在Swift中将数组拆分成两半?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Pragmatic Programmer
Andrew Hunt、David Thomas / Addison-Wesley Professional / 1999-10-30 / USD 49.99
本书直击编程陈地,穿过了软件开发中日益增长的规范和技术藩篱,对核心过程进行了审视――即根据需求,创建用户乐于接受的、可工作和易维护的代码。本书包含的内容从个人责任到职业发展,直至保持代码灵活和易于改编重用的架构技术。从本书中将学到防止软件变质、消除复制知识的陷阱、编写灵活、动态和易适应的代码、避免出现相同的设计、用契约、断言和异常对代码进行防护等内容。一起来看看 《The Pragmatic Programmer》 这本书的介绍吧!