Object.assign执行的是浅拷贝,仅复制对象第一层可枚举自有属性,原始值直接赋值,引用值仅复制内存地址,导致源与目标嵌套对象共享同一实例,修改任一对象的嵌套属性会影响另一对象。

Object.assign 执行的是浅拷贝,赋值后对象属性若为引用类型(如对象、数组、函数等),源对象与目标对象仍共享同一内存地址。
浅拷贝的本质
Object.assign 逐个遍历源对象的**可枚举自有属性**,将属性值直接赋给目标对象。对原始值(string/number/boolean/null/undefined/symbol)是值传递;对引用值(Object、Array、Date、RegExp 等)只是复制了引用地址,而非创建新对象。
- 修改目标对象中某个嵌套对象的属性,源对象对应位置也会变化
- 修改目标对象自身新增的属性,不影响源对象
- 源对象的原型链、不可枚举属性、Symbol 属性不会被拷贝
典型问题示例
例如:
const source = { name: 'Alice', config: { theme: 'dark', lang: 'zh' } };
const target = {};
Object.assign(target, source);
target.config.theme = 'light';
console.log(source.config.theme); // 'light' —— 源对象也被改了
这是因为 target.config 和 source.config 指向同一个对象实例。
立即学习“Java免费学习笔记(深入)”;
如何避免引用共享?
需要深拷贝时,不能依赖 Object.assign,可考虑以下方式:
- 使用结构化克隆(现代浏览器支持):
structuredClone(obj) - 用 JSON 序列化反序列化(仅适用于纯数据,不支持函数、undefined、Date、RegExp 等):
JSON.parse(JSON.stringify(obj)) - 借助 Lodash 的
_.cloneDeep() - 手动递归实现深拷贝(需处理循环引用、特殊类型等边界情况)
什么时候用 Object.assign 是安全的?
在以下场景中,浅拷贝完全够用且高效:
- 合并配置对象,且所有属性都是基础类型(如
{ timeout: 5000, retry: 3 }) - 为对象添加默认字段(
Object.assign({ a: 1 }, defaults)),默认值本身不含嵌套引用 - 临时扩展对象用于单次操作,后续不再复用原对象


















