Object.assign() 和展开运算符在对象合并上有何区别?
请比较 Object.assign() 和对象展开运算符(...)在对象合并与浅拷贝时的异同。
回答
Yahuda
相同点:
- 都是浅拷贝,只复制自身可枚举属性(不包括原型链)
- 同名属性后面的覆盖前面的
- 不会复制 getter(会读取值后复制)
- Symbol 属性也可以复制
不同点:
| 特性 | Object.assign(target, ...sources) | {...obj1, ...obj2} |
|---|---|---|
| 返回值 | 修改并返回 target | 返回新对象 |
| 修改原对象 | ✅ 会修改 target 对象 | ❌ 不修改原对象 |
| 触发 setter | ✅ 会触发 target 上的 setter | ❌ 使用 [[DefineOwnProperty]],不触发 setter |
| 只读属性 | 若 target 有只读属性会抛 TypeError | 正常创建新属性 |
| 使用场景 | 合并到已有对象 | 创建新对象副本 |
| 性能 | 稍快(不创建新对象) | 稍慢(创建新对象) |
示例:
const target = { a: 1 };
const source = { b: 2 };
const result1 = Object.assign(target, source);
console.log(result1 === target); // true(target 被修改)
console.log(target); // { a: 1, b: 2 }
const result2 = { ...source };
console.log(result2 === source); // false(新对象)
// 展开运算符不能合并到已有对象
// 等价写法:Object.assign({}, obj1, obj2) ≈ { ...obj1, ...obj2 }
建议:创建一个新对象用 ...,合并到已有对象用 Object.assign。