JS中深拷贝与浅拷贝
在前端开发时遇到一个问题,在我使用 扩展运算符 ...
或 Object.assign()
进行对象拷贝时,发现修改新对象的嵌套属性会影响原对象。这让我意识到 JavaScript 中的对象拷贝分为浅拷贝和深拷贝两种方式。
一、浅拷贝(Shallow Copy)
浅拷贝是指只复制对象的第一层属性,如果属性值是引用类型(如对象、数组),则只复制其引用地址。
常见浅拷贝方法
Object.assign()
- 展开运算符
...
Array.prototype.slice()
、concat()
示例:
1 | const obj1 = { a: 1, b: { c: 2 } }; |
二、深拷贝(Deep Copy)
深拷贝会递归复制所有层级的属性,两个对象完全独立,互不影响。
常见深拷贝方法
JSON.parse(JSON.stringify(obj))
(有局限:不能拷贝函数、undefined、Symbol、循环引用等)- 第三方库:
lodash.cloneDeep
示例:
1 | const obj1 = { a: 1, b: { c: 2 } }; |
三、在 React 中的应用
React 的 state 不可变性要求我们不能直接修改原对象,而应通过拷贝生成新对象后再 setState。
错误示例(直接修改引用):
1 | const [user, setUser] = useState({ name: "Tom", info: { age: 20 } }); |
正确示例(深拷贝):
1 | const [user, setUser] = useState({ name: "Tom", info: { age: 20 } }); |
推荐使用
immer
、lodash.cloneDeep
等库简化深拷贝操作。
四、手动实现深拷贝的步骤
手动实现一个通用的深拷贝函数,需考虑如下:
- 递归遍历对象和数组
- 处理基本类型、Date、RegExp、Map、Set 等
- 处理循环引用
简单实现(不处理循环引用/特殊对象):
1 | function deepClone(obj) { |
进阶实现(处理循环引用):
1 | function deepClone(obj, hash = new WeakMap()) { |
五、总结
- 浅拷贝只复制一层,深拷贝递归复制所有层级。
- React 状态管理推荐深拷贝,避免直接修改引用。
- 复杂对象使用第三方库或手动实现深拷贝。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Owen's Blog!
评论