Object.assign只进行浅拷贝,不处理嵌套对象合并、Symbol键、不可枚举属性及原型链,且IE不支持;应优先用解构或structuredClone+递归合并。
它只做一层浅拷贝,遇到 target 和 source 中的属性值是引用类型(如 Object、Array)时,只会复制引用地址,不会递归处理。修改合并后对象里的嵌套属性,会意外影响原对象。
Object.assign({ a: { b: 1 } }, { a: { c: 2 } }) 得到的是 { a: { c: 2 } } —— a 被完全覆盖,不是合并 { b: 1, c: 2 }
structuredClone + 递归合并,或者改用 lodash.merge
Object.assign 对 null 或 undefined 源对象会跳过,但对原始值(如 42、"str")会自动包装成对象再读取自有属性(通常结果为空)它只拷贝源对象上可枚举的自有字符串键属性,Symbol 类型的键和 Object.defineProperty 设置的 enumerable: false 属性都会被忽略。

const sym = Symbol('key'); const obj = { a: 1 }; Object.defineProperty(obj, 'b', { value: 2, enumerable: false }); obj[sym] = 3;Object.assign({}, obj) 结果只有 { a: 1 },b 和 sym 都丢了Reflect.ownKeys + 手动遍历,或用 structuredClone(仅限可序列化值)第一个参数是目标对象(target),后续都是源对象(sources)。如果误把空对象写在后面,比如 Object.assign(a, b, {}),最后一个空对象会覆盖前面所有内容,导致 a 变成空对象 —— 这类 bug 不报错,但数据全丢。
Object.assign({}, obj1, obj2) 是安全的(目标是新对象);但 Object.assign(obj1, obj2, {}) 就危险Object.assign({}, {a:1}, {a:2}, {a:3}) → {a:3}
{} 当作第一个参数IE 全系(包括 IE11)都不支持 Object.assign,必须用 polyfill 或转译。另外,它不会拷贝原型上的属性,也不会设置新对象的 __proto__,返回的对象原型永远是 Object.prototype。
myDate.format()),用 Object.assign 合并后得到的是普通 Object,不再有那些方法Object.setPrototypeOf(注意性能与兼容性){ ...obj1, ...obj2 },但注意它也有同样浅拷贝和不可枚举限制const target = { x: 1, y: { z: 2 } };
const source = { y: { w: 3 }, n: 4 };
const result = Object.assign(target, source);
// result === target → true
// result 是 { x: 1, y: { w: 3 }, n: 4 }
// 注意:target.y 原来的 { z: 2 } 已被整个替换,不是合并
真正麻烦的从来不是“怎么合并”,而是“哪些东西你以为合并了,其实没合进去”——比如嵌套对象被覆盖、Symbol 键消失、原型方法丢失,这些都不会报错,只在运行时悄悄出问题。