直接赋值对象只复制引用,需深拷贝实现状态隔离:推荐structuredClone()(现代浏览器支持)、JSON序列化(兼容性好但有类型限制)、Lodash cloneDeep或自定义递归(复杂结构适用),避免浅拷贝陷阱。

直接赋值对象不会创建新对象,而是复制引用,导致多个组件共享同一份状态数据。要实现组件状态隔离,必须创建对象的独立副本,让每个组件操作自己的数据副本。
使用结构化克隆(推荐)
现代浏览器支持 structuredClone(),能深拷贝大多数 JS 值(包括嵌套对象、数组、Map、Set 等),且不破坏原型链和循环引用(有限支持)。
- 用法简单:
const newState = structuredClone(oldState); - 适合初始化状态或 props 解构:
useState(structuredClone(props.initialData)) - 注意兼容性:IE 不支持,Safari 15.4+、Chrome 98+、Firefox 94+ 支持
JSON 序列化反序列化(简单场景可用)
适用于纯数据对象(不含函数、undefined、Date、RegExp、BigInt、Symbol 等)。
- 写法:
const newState = JSON.parse(JSON.stringify(oldState)); - 优点:兼容性好,所有浏览器都支持
- 缺点:会丢失函数、日期对象变成字符串、过滤 undefined 和 Symbol,无法处理循环引用
手动深拷贝或工具库(复杂结构首选)
当状态含函数、Date、正则、自定义类实例等时,需更健壮方案。
- Lodash 的
cloneDeep:稳定可靠,支持各类类型,但增加包体积 - 自定义递归拷贝:适合特定结构,可控性强,例如只深拷贝某几层嵌套
- 避免在渲染中频繁调用深拷贝——尤其大数据量时,可考虑 useMemo 缓存或状态扁平化
避免浅拷贝陷阱
仅用展开运算符 {...obj} 或 Array.from(arr) 只是浅拷贝,嵌套对象仍共享引用。
- 错误示例:
const copy = { ...state }; copy.nested.value = 'new'; → 原 state.nested.value 也被改 - 正确做法:确保所有层级都被复制,特别是表单、树形结构、配置项等多层嵌套状态
- 可在 useEffect 或事件处理器中检查是否意外修改了原始 props,辅助定位问题


















