声明: 本文来自:https://segmentfault.com/a/1190000009542462 仅作收藏
这两在写js时遇到 数据的拷贝问题
如果 数组是 这样子的: let arrOne = [1, 2, 3, 4, 5] ,
1. 如果直接赋值 let arrTwo = arrOne 那么属于浅拷贝 拷贝的是原数组(arrOne)的引用,改变 arrTwo中的任何操作都会改变arrOne.
2. 如果通过 slice(0), concat(), for循环 操作arrOne 得到 arrTwo 这个属于深度拷贝, 修改arrTwo 不会影响 arrOne
如果 数组 这样子的: let arrOne = [{pid: 1}, {pid: 2}]
1. 通过 clice(0) concat() 不能进行 深度拷贝 修改 拷贝后的操做 依然会影响 arrOne
所以才有了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://lodash.com/docs/4.17.10#cloneDeep