浅谈JavaScript中的深拷贝和浅拷贝
前言
之前一直觉得在深拷贝和浅拷贝上没遇到过什么问题,因此也没有太留意。前段时间在写项目的时候突然遇到了相关问题,因此决定还是简单地做个记录以备之后需要。
问题引入
直接进入正题,我们引入一个例子,这样将更有助于我们学习深/浅拷贝的区别。
问题:存在一个数组 a
, 其内部存放的元素是 point
对象。 现在我要获取数组的最后一个元素并保存为 b
, 然后利用循环将数组 a
中的每一个元素的值等于前一个元素的值, 最后 b
的值是否会改变? 如果改变, 又如何让它不变?
解决方案
浅拷贝
很显然, 如果直接用 b = a[a.length - 1]
这种赋值方式时,b
和 a[a.length - 1]
都存储在栈内存中。它们都只是对应堆内存中的 point
元素的引用,指向一个地址。(并没有在堆内存中创建新的 point
元素)
当对 point
对象的值进行修改时,会发现 b
对应的值也会修改,这就是 浅拷贝。
1 | // 定义 point 对象 |
那么如何解决这种问题并且实现我们想要的结果呢?👉 深拷贝
深拷贝
深拷贝和浅拷贝的主要区别就在于:如何应对复杂的Object对象。
🌟 深拷贝会在堆内存中新建一个同样的对象, 并在栈内存中创建指向该对象的引用, 即 b
。
1 | import _ from 'lodash'; // 借助 lodash 实现深拷贝 |
我们也可以利用 ===
来判断一下 深浅拷贝和原值是否完全相等。
1 | console.log(b === a[a.length - 1]) // true 浅拷贝 |
总结
由上面的实例,我们大致地了解了深/浅拷贝的区别。虽然浅拷贝无法解决像上述的问题,但是在绝大多数情况下,我还是建议使用浅拷贝,因为浅拷贝可以满足我们绝大多数需求。
如果不是遇到必须使用深拷贝的情况,请不要随意使用深拷贝。因为深拷贝的深度复制容易带来性能问题,尤其是当复制的对象层级复杂时。
因此,要根据实际情况合理使用深/浅拷贝。
很感谢你能看到这里!谢谢~
参考资料: (衷心感谢各参考资料提供的帮助)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 窦晨的博客!
评论