你真的理解深拷贝与浅拷贝了吗?

简单来说,深拷贝主要是将另一个对象的属性值拷贝过来之后,另一个对象的属性值并不受到影响,因为此时它自己在堆中开辟了自己的内存区域,不受外界干扰。
浅拷贝主要拷贝的是对象的引用值,当改变对象的值,另一个对象的值也会发生变化。
我们看一个基本数据类型的列子,let a = 1命令会在栈内存中开辟一块区域,之后拷贝一个a对象给b,如图所示

你真的理解深拷贝与浅拷贝了吗?_第1张图片
我们可以看到,在栈内存中也为b开辟了一块内存区域,此时a,b的赋值互不干扰,当改变a对象属性值时b不受影响,这其实就完成了我们所谓的简单深拷贝,但并不能完全称作深拷贝,因为深拷贝本身就针对的是复杂的Object类型数据,并且深拷贝需要将属性的各个层级都要拷贝过来,刚刚的例子只有一个层级。
我们开看一个js中的slice()方法,这个方法其实并不能达到完全的深拷贝,
你真的理解深拷贝与浅拷贝了吗?_第2张图片
可以看到,当改变a[0]的值后,打印处a的值改变为[2,2,3,4],b的值并不受到影响,仍然是[1,2,3,4],可以深拷贝成功,slice()这个方法表面上具有深拷贝的功能,但之后换一个多一层级别的数组,
你真的理解深拷贝与浅拷贝了吗?_第3张图片
可以看出,slice()这个方法拷贝的并不彻底,一级属性可以完全拷贝过来,不受a改变的影响,但是二级属性还是没能拷贝成功,仍然脱离不了a的控制,说明slice根本不是真正的深拷贝。同理,concat方法与slice也存在这样的情况,他们都不是真正的深拷贝,这里需要注意。说一下,JSON.stringify与JSON.parse可以实现深拷贝。

接下来可以借引用数据类型来说一下浅拷贝,浅拷贝其实没有什么特别之处,如图所示
你真的理解深拷贝与浅拷贝了吗?_第4张图片
浅拷贝其实拷贝的是它的引用地址,let a = [0,1,2,3,4,5]; b = a;
b拷贝了a在栈中的堆地址,都指向a在堆中的属性值,当a数组放生改变时,b属性值也会改变,因为b也指向相同的堆内存。

文章参考文献:https://www.cnblogs.com/echolun/p/7889848.html

你可能感兴趣的:(Java面试)