Object.assign 是浅拷贝方法,只复制第一层属性引用,不递归处理嵌套对象;对基本类型赋值,对引用类型赋内存地址,修改嵌套属性会影响原对象。

Object.assign 本身就是一个浅拷贝方法,它把源对象(source)的所有可枚举自有属性复制到目标对象(target),返回目标对象。这个过程不递归处理嵌套对象,只复制第一层属性的引用——这就是“浅拷贝”的本质。
它怎么工作的?
Object.assign 的行为可以理解为:遍历每个源对象的可枚举自有属性(不包括原型链上的属性、不可枚举属性、Symbol 属性),用 = 赋值的方式把值写入目标对象。对于基本类型(string/number/boolean/null/undefined),赋的是值;对于对象、数组、函数等引用类型,赋的是内存地址(即引用)。
一个典型例子说明浅拷贝特性
比如:
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = Object.assign({}, obj1);
obj2.a = 99; // 修改基本类型属性 → 不影响 obj1
obj2.b.c = 88; // 修改嵌套对象属性 → obj1.b.c 也变成 88!
因为 obj2.b 和 obj1.b 指向同一个对象,Object.assign 并没有创建新对象来替代 b。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
手写一个简易版 Object.assign(仅支持对象参数)
可以这样模拟核心逻辑:
function myAssign(target, ...sources) {
if (target == null) throw new TypeError('Cannot convert undefined or null to object');
const to = Object(target); // 确保 target 是对象
for (const source of sources) {
if (source != null) {
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
to[key] = source[key]; // 直接赋值,不递归
}
}
}
}
return to;
}
注意点:
- 会跳过 null/undefined 源对象
- 只遍历自有可枚举属性(用 hasOwnProperty 判断)
- 不处理 Symbol 属性(原生 Object.assign 支持,这里简化了)
- 对 getter/setter 属性,会触发 getter 获取值后赋值,不会保留访问器特性
什么时候不能用 Object.assign 做浅拷贝?
以下情况需谨慎或换方案:
- 需要深拷贝嵌套结构 → 改用 structuredClone、JSON.parse(JSON.stringify())(有局限)或 Lodash 的 cloneDeep
- 要拷贝不可枚举属性(如 length、__proto__)或 Symbol 属性 → 需配合 Object.getOwnPropertyDescriptors + Object.defineProperties
- 源对象有 getter,你希望保留响应式行为 → Object.assign 只取当前值,不保留 getter
- 目标对象是冻结对象(Object.freeze)→ 赋值会静默失败(非严格模式)或报错(严格模式)
不复杂但容易忽略:浅拷贝不是“安全拷贝”,它只是第一层的“断连”,深层仍共享引用。用之前想清楚数据结构是否嵌套。

















