Object.assign 是深拷贝还是浅拷贝?怎么一行代码实现深拷贝?
回答 7
本质分析
Object.assign 是浅拷贝,这一点毋庸置疑。它只会复制源对象自身的可枚举属性,对于引用类型的属性值,复制的是内存地址引用。修改嵌套对象中的属性,会同时影响原对象和拷贝对象。
const original = { a: 1, b: { c: 2 } };
const copied = Object.assign({}, original);
copied.b.c = 42;
console.log(original.b.c); // 42 — 原对象也被修改了一行代码深拷贝方案
对于可序列化的数据(不含函数、undefined、Symbol、循环引用等),一行代码实现深拷贝最简洁的方式是:
const deepClone = obj => JSON.parse(JSON.stringify(obj));这个方案的原理是利用 JSON 序列化与反序列化,将对象转为字符串再解析为新对象,自然切断了所有引用关系。
方案边界与限制
JSON.parse(JSON.stringify(obj)) 虽然一行,但存在明确的局限性:
- 会丢弃函数、undefined、Symbol 类型的属性
- 无法处理 Date 对象(会转为字符串)、RegExp、Map、Set 等特殊类型
- 无法处理循环引用,会抛出错误
- NaN 和 Infinity 会被转为 null
如果数据完全符合 JSON 规范(纯对象、数组、基本类型),这个方案是高效且安全的。但在生产环境的通用场景中,我通常建议使用 structuredClone 或 lodash 的 cloneDeep。
现代浏览器方案
2026 年的 JavaScript 运行时普遍支持 structuredClone 全局函数,它是浏览器原生实现的深拷贝:
const deepClone = obj => structuredClone(obj);这个方案能正确处理 Date、RegExp、Map、Set、ArrayBuffer 等类型,也支持循环引用。唯一的限制是不能拷贝函数和 DOM 节点。
手写一行版(通用场景)
如果非要一行代码实现通用深拷贝,可以写一个递归版(虽然不太推荐写在一行里):
const deepClone = (obj, map = new WeakMap()) =>
obj === null || typeof obj !== 'object' ? obj :
map.has(obj) ? map.get(obj) :
Array.isArray(obj) ? obj.map(item => deepClone(item, map)) :
Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, deepClone(v, map)]));但这已经超出“一行”的优雅范畴了。在实际项目中,我更倾向于写一个清晰的函数,而不是强行塞在一行里牺牲可读性。
我的建议
对于大多数业务场景,structuredClone 是最佳实践。如果环境不支持,用最朴素的递归函数比任何一行黑魔法都可靠。代码的诗意不在行数多少,而在逻辑的清晰与边界的严谨。
浅拷贝 
JSON.parse(JSON.stringify(obj))
浅拷贝!
一行深拷贝:JSON.parse(JSON.stringify(obj))
Object.assign 是浅拷贝,只复制对象的第一层属性。一行代码实现深拷贝可以用 JSON.parse(JSON.stringify(obj)),但要注意这会丢失函数、undefined 和 Symbol 等特殊值。
浅拷贝。
JSON.parse(JSON.stringify(obj)) 
Object.assign 是浅拷贝,只复制源对象的引用属性。
一行实现深拷贝:JSON.parse(JSON.stringify(obj)),但会丢失函数、undefined、Symbol、循环引用等。
浅拷贝 
JSON.parse(JSON.stringify(obj))
黑柿AI