展开运算符仅执行浅拷贝,只复制第一层属性,嵌套对象仍共享引用;深拷贝则递归复制所有层级,完全隔离数据,但有性能开销和兼容性限制。

展开运算符(...)和深拷贝都能创建新对象,但它们在不可变数据场景下的行为、适用范围和风险完全不同。展开运算符只做浅拷贝,对嵌套对象无效;深拷贝能真正隔离嵌套结构,但需注意性能和循环引用问题。
展开运算符:快但只管一层
展开运算符常用于数组或对象的“表层”复制,语法简洁,执行高效,但它只会复制第一层属性的值(对基本类型是值拷贝,对引用类型是地址拷贝)。
- 适用于扁平结构,比如更新对象顶层字段:
const newObj = { ...oldObj, name: 'Alice' }; - 对嵌套对象完全无效:
const user = { profile: { age: 30 } }; const copy = { ...user }; copy.profile.age = 31;→user.profile.age也会变成 31 - 无法处理函数、Date、RegExp 等特殊对象,它们仍被浅层引用
深拷贝:彻底但有代价
深拷贝会递归复制所有层级,确保原始数据与副本完全独立。常见实现包括 JSON.parse(JSON.stringify())、结构化克隆(structuredClone())、或第三方库如 Lodash 的 cloneDeep。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
structuredClone()是现代推荐方案,支持 Map、Set、Date、RegExp 和嵌套对象,且能处理循环引用(部分环境) -
JSON方式简单但有严重限制:丢失函数、undefined、Symbol、BigInt,不支持循环引用,Date 变成字符串 - 深拷贝开销明显,尤其对大型嵌套对象,可能引发性能瓶颈或内存压力
不可变更新的实际选择策略
真正的不可变性不等于“必须深拷贝”,而是在需要修改时精准切断引用链。多数场景下应优先组合使用展开运算符 + 手动深层覆盖,而非无脑深拷贝。
立即学习“Java免费学习笔记(深入)”;
- 更新深层字段时,逐层展开:
{ ...state, user: { ...state.user, profile: { ...state.user.profile, age: 31 } } } - 对复杂嵌套结构,可封装工具函数或用 Immer 这类库,在保持代码可读的同时自动处理不可变更新
- 仅当结构动态未知或嵌套极深时,才考虑
structuredClone;避免在高频操作(如渲染循环)中调用
关键区别一句话总结
展开运算符是轻量、可控、易推理的浅层不可变操作;深拷贝是重型、彻底、但可能低效或失真的全量隔离手段。选哪个,取决于你的数据形状、变更深度和运行环境约束。

















