Object.assign和扩展运算符均实现浅拷贝,仅复制第一层属性值,嵌套对象仍共享引用;前者适用于动态多源合并与旧环境兼容,后者语法更简洁直观且推荐用于单对象拷贝。

ES6 中用 Object.assign 和扩展运算符(...)实现浅拷贝,核心是“只复制第一层属性值,不处理嵌套对象或数组的引用”。两者本质相同,都是浅拷贝,但写法和适用场景略有差异。
Object.assign 实现浅拷贝
Object.assign() 把一个或多个源对象的可枚举属性复制到目标对象,并返回目标对象。做浅拷贝时,通常传入一个空对象作为目标:
- 语法:
const newObj = Object.assign({}, originalObj); - 它会遍历
originalObj自身所有可枚举属性,把键值对复制进新对象 - 如果
originalObj某个属性值是对象(如{a: {b: 1}}),那复制过去的是该对象的引用,不是副本 - 注意:第一个参数是目标对象,会被修改;所以必须传新对象(如
{}),避免污染原对象
扩展运算符实现浅拷贝
扩展运算符在对象字面量中展开源对象,生成一个新对象:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 语法:
const newObj = { ...originalObj }; - 效果等同于
Object.assign({}, originalObj),也是只展开第一层属性 - 支持合并多个对象:
const merged = { ...obj1, ...obj2 };,后者的同名属性会覆盖前者 - 不能直接用于类数组对象或 Map/Set 等,仅适用于普通对象和可遍历对象
浅拷贝的典型陷阱
无论用哪种方式,只要原始对象里有嵌套结构,改动嵌套内容就会相互影响:
立即学习“Java免费学习笔记(深入)”;
- 例如:
const a = { x: 1, y: { z: 2 } }; const b = { ...a }; - 执行
b.y.z = 99后,a.y.z也会变成99 - 这是因为
b.y和a.y指向同一个内存地址 - 要真正隔离嵌套数据,必须用深拷贝(如
JSON.parse(JSON.stringify(obj))或递归函数)
什么时候选哪个?
两者功能高度重合,选择主要看代码风格和需求:
- 需要合并多个对象或带默认值时,扩展运算符更简洁:
{ ...defaults, ...userInput } - 需要动态传入多个源对象(比如用数组收集),
Object.assign更灵活:Object.assign({}, ...sources) - 兼容性要求高(需支持 IE)?
Object.assign可 polyfill,扩展运算符不行 - 纯拷贝单个对象,二者任选,推荐扩展运算符——更直观、不易误写成
Object.assign(original, {})这种反向操作

















