浅拷贝本质是复制引用而非数据,导致修改副本时原数组同步变更;典型表现包括跨组件状态污染、json序列化丢失特殊类型、循环引用崩溃及并发场景竞态覆盖。

数组拷贝出问题,核心就一条:你以为复制了一份,其实只是多了一个指针。真正变的不是值,而是谁在用那一块内存。
修改副本,原数组跟着变
这是最典型的浅拷贝 Bug。比如用 =、Array.from()(不带映射)、或 slice(0) 复制一个含嵌套对象/数组的结构:
-
const a = [{ name: 'Alice' }]; const b = a.slice(); b[0].name = 'Bob';→a[0].name也变成'Bob' - 表单组件接收父级传来的数组,直接 push 或 splice,结果父组件状态意外更新
- 后端返回的原始数据被某处“临时处理”后污染,导致重试、回滚或二次渲染失败
类型丢失引发隐性失效
用 JSON.parse(JSON.stringify()) 做“深拷贝”时,Date、RegExp、undefined、function、BigInt、Map、Set 等类型会被丢弃或转成空值:
-
const arr = [new Date(), /test/, undefined]; JSON.parse(JSON.stringify(arr))→[null, {}, null] - 时间字段变成字符串或 null,正则校验逻辑失效,函数回调丢失
- 看似拷贝成功,但运行时抛错或行为异常,且 console.log 看不出差别
循环引用导致卡死或崩溃
当数组或其元素内部存在自引用、双向引用(如树节点 parent/children)时,朴素递归拷贝会无限展开:
-
const obj = {}; obj.self = obj;→JSON.stringify(obj)报错,structuredClone(obj)在支持环境下可安全处理 - lodash.cloneDeep 默认不开启循环检测,需显式配置;否则可能内存溢出或长时间无响应
- 微前端子应用收到主应用传入的含循环结构的配置,初始化阶段直接挂掉
多线程/异步场景下的竞态覆盖
数组拷贝本身不是原子操作,尤其在并发修改+浅拷贝混合使用时:
- 多个定时器或 Promise 回调同时对同一源数组做
concat()后修改,再赋值回 state,造成中间状态丢失 - Web Worker 传递数组前未深拷贝,主线程与 Worker 共享 ArrayBuffer 视图,写入冲突
- React 中 useEffect 依赖项没设全,导致旧副本被重复复用,叠加修改











