本篇文章咱们一起来学习下JS中的浅拷贝和深拷贝,了解它们在内存上的区别,并掌握浅拷贝和深拷贝的常用实现方法。
引用赋值
在学习拷贝之前,咱们先来看一个常见的情景,如下图:
大家觉得这是深拷贝还是浅拷贝,或者是其他的?
答案是这种方式是引用赋值,它既不是深拷贝,也不是浅拷贝。在内存上的体现是person1和person2的内存指针都指向同一个堆内存对象,验证方式如下图:
从输出结果可以看到修改person1和surname属性,person2的surname属性也发生了更改。
浅拷贝
浅拷贝比较常见的实现方法是通过展开运算符(展开运算符被允许使用在对象字面量声明的时候),如下图:
在内存上的体现是person1和person2分别指向不同的堆内存对象,验证方式如下图:
从输出结果可以看到person2的surname属性并没有因为person1的surname属性发生改变而改变。
深拷贝
通常用于复杂类型的拷贝,同时咱们也可以用来反向证明一下展开运算符是浅拷贝,代码如下图:
从输出结果可以看到,1号小人的朋友从钱姓朋友变成了孙姓朋友,而2号小人的朋友姓氏也随之改变,这就说明person1和person2的friend指向的是同一个堆内存对象,而深拷贝需要将嵌套的每一层的对象都拷贝成全新的堆内存对象,常用的实现方法如下图:
通过JSON.stringify方法将person1对象转为JSON,再通过JSON.parse方法将JSON字符串转化为全新的JS对象,从而实现深拷贝,验证方式如下图:
从输出结果可以看到,1号小人的朋友从钱姓朋友变成了孙姓朋友,2号小人的朋友仍然是钱姓朋友。