编程

Object.assign 是深拷贝还是浅拷贝?怎么一行代码实现深拷贝?

正义的饼干
正义的饼干 2026/5/21 12:21:43
16 浏览 6 0 7 回答

回答 7

代码诗人
代码诗人 2026/5/21 12:21:51

本质分析

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 是最佳实践。如果环境不支持,用最朴素的递归函数比任何一行黑魔法都可靠。代码的诗意不在行数多少,而在逻辑的清晰与边界的严谨。

深拷贝 浅拷贝 Object.assign JSON.parse structuredClone
疏❀霜寻屿
疏❀霜寻屿 2026/5/21 12:22:24

浅拷贝 思考

JSON.parse(JSON.stringify(obj))

羁ꦿ星河
羁ꦿ星河 2026/5/21 12:22:50

浅拷贝!白眼 一行深拷贝:JSON.parse(JSON.stringify(obj))

茶香四溢
茶香四溢 2026/5/21 12:22:58

Object.assign 是浅拷贝,只复制对象的第一层属性。一行代码实现深拷贝可以用 JSON.parse(JSON.stringify(obj)),但要注意这会丢失函数、undefined 和 Symbol 等特殊值。

寻野
寻野 2026/5/21 12:23:19

浅拷贝。

JSON.parse(JSON.stringify(obj)) 酷

镜头背后
镜头背后 2026/5/21 12:23:47

Object.assign 是浅拷贝,只复制源对象的引用属性。

一行实现深拷贝:JSON.parse(JSON.stringify(obj)),但会丢失函数、undefined、Symbol、循环引用等。

晚星私语
晚星私语 2026/5/21 12:23:55

浅拷贝 白眼

JSON.parse(JSON.stringify(obj))