资讯专栏INFORMATION COLUMN

js中的数组深拷贝

lily_wang / 2100人阅读

摘要:好久没写文章了,都感觉自己最近没什么进步啊,正愁不知道写什么呢,这两天的工作中偶然发现一个数组深拷贝的问题,正好可以拿出来说一说。难道之前我们对数组的深拷贝都被骗了。。。对于字符串数字及布尔值来说不是或者对象,会拷贝这些值到新的数组里。

好久没写文章了,都感觉自己最近没什么进步啊,正愁不知道写什么呢,
这两天的工作中偶然发现一个js数组深拷贝的问题,正好可以拿出来说一说。

抛出问题
const arr = [{name: "wens"},{age: "26"}];    //原数组  
const newArr1 = arr.slice(0);  
const newArr2 = arr.concat();  
newArr2[0].name = "leon";  
newArr2[1].age = "27";  

在控制台打印之后发现,尼玛arr,newArr1,newArr2打印的东西完全一样完全一样完全一样

[{name: "leon"},{age: "27"}];

说好的对数组进行slice或concat操作都是拿出一块新的内存空间存放新的数组,而不是对原数组的引用呢。难道之前我们对数组的深拷贝都被“骗了”。。。
别担心,下面,我们一步步来分析分析

从复制说起

抛开slice,concat方法不说,最原始复制一个数组的方法是什么

var arr = [1,2,3]
var newArr = arr

优点:方便
缺点:由于数组是引用类型(不懂基本类型和引用类型的自行补课),修改了arr或者newArr中的一个会影响全部

既然大家都知道赋值的缺点,所以才有了slice,concat方法。
重点来了,搬好小板凳做好听课:

slice 不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:
如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
如果向两个数组任一中添加了新元素,则另一个不会受到影响。

引用MDN中的话,翻译成白话:
数组中的值如果是引用类型,对其进行增删改,会影响用slice复制的数组,
但是如果数组中的值是基本类型,就不会影响
现在回头看开篇提出的那个问题,就很好理解了,因为数组里面是obj,而obj是引用类型,所以当然修改了newArr,arr里面的值也修改了
其实,工作中遇到的很多奇奇怪怪的问题大部分都是对知识点的模棱两可,仔细看文档就能解决的问题,所以说学好技术有时候并没有大家想的那么简单,仔细仔细仔细,认真认真认真能做到这两点的人好少啊

解决方案

1、简单粗暴:

newArr1 = JSON.parse(JSON.stringify(arr));

这种方式能够满足99%的深拷贝(如开篇的例子),但是对与RegExp类型和Function类型则无法完全满足,而且不支持有循环引用的对象。

2、现成的lodash库:_.cloneDeep

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88285.html

相关文章

  • Js之浅拷贝拷贝与对象数组的遍历

    摘要:判断是深拷贝对象还是数组如果要拷贝的对象的属性依然是个复合类型,递归运用递归,当要拷贝的对象或者数组的属性依然是个对象或者数组时,递归调用。遍历对象聊完了深拷贝和浅拷贝,接下来说一下遍历。 在js这门语言中,数据存放在堆中,而数据的引用的存放在栈中。 浅拷贝 我们说的浅拷贝,指的是,引用地址的拷贝,栈中两块不同的引用地址都指向了堆中同样一块区域。所以,我们通过一个地址修改了堆中的数据,...

    liangzai_cool 评论0 收藏0
  • 浅探js拷贝和浅拷贝

    摘要:接下来就让我们更细致的探究中的深浅拷贝。总结以上对深拷贝和浅拷贝做了简单的介绍,在深拷贝的实现上也只介绍了最简单的实现形式,并未考虑复杂情况以及相应优化,想要对深拷贝有更深入的了解,需要大家花时间去深入研究,或者可以关注我后续文章的动态。 对象和数组的拷贝对我来说一直都是一个比较模糊的概念,一直有点一知半解,但是在实际工作中又偶尔会涉及到,有时候还会一不小心掉坑里,不知道大家有没有同样...

    habren 评论0 收藏0
  • JS专题之拷贝

    摘要:在之前的文章专题之数据类型和类型检测中我有讲过,中的数据类型分为两种,基本数据类型和引用数据类型,基本数据类型是保存在栈的数据结构中的是按值访问,所以不存在深浅拷贝问题。 前言 在开发过程中,偶尔会遇到这种场景,拿到一个数据后,你打算对它进行处理,但是你又希望拷贝一份副本出来,方便数据对比和以后恢复数据。 那么这就涉及到了 JS 中对数据的深浅拷贝问题,所谓深浅拷贝,浅拷贝的意思就是,...

    ASCH 评论0 收藏0
  • JS 中的拷贝与浅拷贝

    摘要:什么是深拷贝浅拷贝见名知义,无论是深拷贝还是浅拷贝,都是的问题。使用如下以上就是关于中的深拷贝与浅拷贝的知识和如何进行深拷贝的知识了,如果有错或者有其他方式的话,欢迎在下面留言评论啦 前言 最近在写项目的时候涉及到一些父子组件传递个对象或者数组通信啥的,或者是直接复制添加对象啥的,直接使用赋值的时候总会出错。一查原来是浅拷贝的问题,就从网上找了点资料,汇总到这里来了。 1 什么是深拷贝...

    ztyzz 评论0 收藏0
  • ​搞不懂JS中赋值·浅拷贝·拷贝的请看这里

    showImg(https://segmentfault.com/img/bVbvpCA); 前言 为什么写拷贝这篇文章?同事有一天提到了拷贝,他说赋值就是一种浅拷贝方式,另一个同事说赋值和浅拷贝并不相同。我也有些疑惑,于是我去MDN搜一下拷贝相关内容,发现并没有关于拷贝的实质概念,没有办法只能通过实践了,同时去看一些前辈们的文章总结了这篇关于拷贝的内容,本文也属于公众号【程序员成长指北】学习路线...

    lauren_liuling 评论0 收藏0

发表评论

0条评论

lily_wang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<