js中的数组深拷贝

很久没写文章了,都感受本身最近没什么进步啊,正愁不知道写什么呢,
这两天的工做中偶然发现一个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打印的东西彻底同样彻底同样彻底同样spa

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

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

从复制提及

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

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

优势:方便
缺点:因为数组是引用类型(不懂基本类型和引用类型的自行补课),修改了arr或者newArr中的一个会影响所有对象

clipboard.png

既然你们都知道赋值的缺点,因此才有了slice,concat方法。
重点来了,搬好小板凳作好听课:blog

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

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

解决方案

一、简单粗暴:文档

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

这种方式可以知足99%的深拷贝(如开篇的例子),可是对与RegExp类型和Function类型则没法彻底知足,并且不支持有循环引用的对象。字符串

二、现成的lodash库:_.cloneDeep

相关文章
相关标签/搜索