(共566篇)
全部分类

js中的深拷贝与浅拷贝
[ JS基础 ] 

在业务开发中经常会遇到需“从老数组拷贝出一份新数组,且两者互不影响的”的需求,这里记录一下用到的方法。

先说一下什么叫深拷贝与浅拷贝。

浅拷贝

大家应该都在电脑中用过“创建快捷方式”的功能吧,假设有一个文件“a.text”,如果我们在这个文件上创建了两个快捷方式,并且分别命名为“b.text"和"c.test"

现在这三个文件,不管通过那个文件打开后修改里面的内容,保存关闭后,打开其他连个文件,会发现文件的内容也跟着变化了。

这是因为虽然三个文件的名字不同,但它们指向的文件实际上是同一个,在往深层次说,就是他们指向的内存地址是相同的,所以从三个文件中的任何一个文件打开修改,实际上修改的都是同一份数据,这就是浅拷贝

深拷贝

那么,如果我们通过“复制-粘贴”功能,再创建一个新的文件“d.text”呢?我们在"d.text"文件中修改一部分内容,会发现"a.text"文件并没有改变。这是以为虽然通过“复制-粘贴”功能,我们把"a.text"文件的所有内容复制了一份,并且放到了硬盘的另一个区域,这两个区域是互不影响的,这种拷贝的方式就叫做“深拷贝”。

JS 中的浅拷贝与深拷贝

我们都知道数据类型分为两种,一种是基本数据类型(也叫原始数据类型),比如String,Number,Boolean,null,undefined,Symbol,Function,另一种叫引用数据类型,比如Object,Array,Function

我们常说的深拷贝和浅拷贝,主要发生在 Object,Array 以及 Set、Map 等 F 数据类型之中,因为他们的元素可以由各种数据类型组合而成,也叫做符合数据类型。

而深拷贝和浅拷贝,主要发生在这几种符合数据类型的元素上。

元素的值 属于基本数据类型的时候,这个值在拷贝的时候,会进行深拷贝;

1
2
3
let a = ['zhangsan', 10, true, null, undefined, Symbol('a')];
let b = a;
console.log(b); // ["zhangsan", 10, true, null, undefined, Symbol(a)]

如果 元素的值 属于"引用数据类型",就会发生“浅拷贝”的情况。

来看一下发生了“浅拷贝”的例子:

1
2
3
4
5
let obj = { name: 'lily' };
let a = [obj];
console.log(a); // [{ name: 'lily' }]
obj.name = 'david';
console.log(a); // [{ name: 'david' }]

上面的代码中,我们明明只修改了 obj 的 name 属性,变量 a 的内容也发生了改变。

这是因为 obj 是一个引用数据类型,变量 a 第一个元素,实际上引用的是 obj 的内存地址,当 obj 的内容发生了变化,变量 a 的内容也跟着发生了变化。那么如何让数组内的符合数据类型实现深拷贝呢?

1
2
3
4
5
let a = [{ name: 'lily' }];
let b = JSON.parse(JSON.stringify(a));
a[0].name = 'david';
console.log(a); //[ { name: 'david' } ]
console.log(b); //[ { name: 'lily' } ]