在 JavaScript 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是复制对象的两种不同方法,它们的区别在于对嵌套对象的处理方式:
浅拷贝(Shallow Copy)
浅拷贝仅复制对象的第一层属性,对于嵌套的对象或数组,仅复制引用,而不复制内容本身。因此,修改嵌套对象会影响到原始对象。
浅拷贝的方法:
-
Object.assign
:const obj = { a: 1, b: { c: 2 } }; const shallowCopy = Object.assign({}, obj); shallowCopy.b.c = 42; console.log(obj.b.c); // 输出 42
-
展开运算符 (
...
):const obj = { a: 1, b: { c: 2 } }; const shallowCopy = { ...obj }; shallowCopy.b.c = 42; console.log(obj.b.c); // 输出 42
深拷贝(Deep Copy)
深拷贝会递归复制对象的所有属性,包括嵌套对象和数组,从而创建一个完全独立的副本,修改副本不会影响原始对象。
深拷贝的方法:
-
JSON.parse
和JSON.stringify
(简单且常用,但有局限性):const obj = { a: 1, b: { c: 2 } }; const deepCopy = JSON.parse(JSON.stringify(obj)); deepCopy.b.c = 42; console.log(obj.b.c); // 输出 2
局限性:
- 不能拷贝函数、
undefined
、Symbol
等特殊类型。 - 日期对象会变成字符串。
- 循环引用的对象会导致错误。
- 不能拷贝函数、
-
递归实现:
手动递归实现深拷贝。function deepClone(obj) { if (obj === null || typeof obj !== 'object') { return obj; } const copy = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { copy[key] = deepClone(obj[key]); } } return copy; } const obj = { a: 1, b: { c: 2 } }; const deepCopy = deepClone(obj); deepCopy.b.c = 42; console.log(obj.b.c); // 输出 2
-
使用 Lodash 的
cloneDeep
:
如果你的项目中可以引入第三方库,Lodash
提供了可靠的深拷贝函数:const _ = require('lodash'); const obj = { a: 1, b: { c: 2 } }; const deepCopy = _.cloneDeep(obj); deepCopy.b.c = 42; console.log(obj.b.c); // 输出 2
-
现代工具如
structuredClone
:
在现代浏览器中,structuredClone
是一种支持多种类型的深拷贝方法。const obj = { a: 1, b: { c: 2 } }; const deepCopy = structuredClone(obj); deepCopy.b.c = 42; console.log(obj.b.c); // 输出 2
总结
- 浅拷贝适用场景:仅需要复制对象的第一层,不需要处理嵌套结构。
- 深拷贝适用场景:对象结构复杂,需要独立修改嵌套属性。
- 根据实际需求选择适合的拷贝方式,复杂场景建议使用可靠的工具如 Lodash 或
structuredClone
。