structuredclone() 是当前最简可靠的深克隆方式,支持循环引用及 date/map/set 等类型,但不支持函数、promise、dom 节点等;遇不支持项抛 datacloneerror;大 arraybuffer 可用 transfer 零拷贝;不保留原型链,类实例需手动重建。

直接用 structuredClone() 就是当前最简、最可靠的对象深克隆方式——它原生支持循环引用、保留 Date/Map/Set/RegExp/ArrayBuffer 等类型,且不依赖序列化字符串,性能优于 JSON 方案。
明确支持与不支持的类型,避免运行时报错
structuredClone 不是“万能拷贝”,提前知道边界才能写得稳:
- ✅ 安全支持:普通对象、数组、Date、RegExp、Map、Set、Error、Blob、File、BigInt、ArrayBuffer、TypedArray(如 Uint8Array)、循环引用结构
-
❌ 明确不支持:函数、Promise、Proxy、WeakMap、WeakSet、DOM 节点(Element/document)、undefined 属性、Symbol 键(除非是
Symbol.for('key'))、getter/setter(值被静态拷贝,逻辑不执行) - 遇到不支持项会直接抛
DataCloneError,而不是静默丢弃——这是优点,也是提醒你检查数据结构
大二进制数据用 transfer 零拷贝转移
对 ArrayBuffer 或 TypedArray 类型的大内存(如视频帧、音频缓冲),用 transfer 选项可避免复制开销,实现“移动”而非“拷贝”:
- 写法:
structuredClone(obj, { transfer: [buffer] }) - 执行后原
buffer变为 detached(byteLength === 0),不可再读写 - 只接受
ArrayBuffer、MessagePort等可转移对象;传Uint8Array本身会报错 - 适合向 Web Worker 传递高频大数据,但业务逻辑中需确保转移后不再访问原 buffer
兼容性判断与降级策略要务实
不必强行兼容所有旧环境,按实际需求选择降级方式:
- 检测是否可用:
typeof structuredClone === 'function'(比'structuredClone' in window更准) - 若确定数据含循环引用或 Map/Set,就不要 fallback 到 JSON(JSON 会直接报错或丢失类型)
- 纯数据对象(无 Date/Map/循环)且需兼容老浏览器,可用
JSON.parse(JSON.stringify(obj)),但需注意:丢失类型、不支持 undefined、不处理循环 - 需要强兼容又不愿引入 lodash,可用轻量 polyfill(自动检测原生支持,无外部依赖)
不保留原型链,业务类实例需额外处理
structuredClone 返回的是 plain object,不会保留原始 constructor 或原型方法:
- 例如
class User { ... }的实例克隆后变成普通对象,instanceof User为 false - 如果业务依赖类实例行为,克隆后需手动重建实例:
Object.assign(new User(), clone)或调用构造函数重新初始化 - Map/Set 内部键值若为 class 实例,其原型信息同样丢失,仅保留可克隆字段











