structuredClone是现代JavaScript最接近“开箱即用”的原生深拷贝方案,支持Date、RegExp、Map、Set等类型并自动处理循环引用,但不支持函数、Promise、Symbol、DOM节点等,遇不可克隆值直接抛出DataCloneError。

structuredClone 是现代 JavaScript 中最接近“开箱即用”的深拷贝原生方案,但它不是万能的。它明确拒绝不可序列化的值,直接抛出 DATA_CLONE_ERR 错误,而不是静默忽略或降级处理——这是设计原则,不是缺陷。
明确不支持的数据类型
以下类型在传入 structuredClone 时必然触发 TypeError:
- 函数(普通函数、箭头函数、class 方法、getter/setter)
-
undefined和Symbol(包括Symbol('a')) -
Promise、WeakMap、WeakSet、Proxy、Generator - DOM 节点(
Element、Document、window、document.body等宿主对象) - 带有循环引用的对象(即使全是可克隆类型,也会报错)
它能处理但容易被误解的类型
有些类型看似“特殊”,其实 structuredClone 原生支持,无需额外处理:
-
Date对象 → 克隆后仍是Date实例(不是字符串) -
RegExp对象 → 克隆后仍是RegExp实例(不是空对象) -
Map、Set、ArrayBuffer、TypedArray、Blob、File、ImageData -
null、BigInt、undefined(注意:undefined在对象属性中会被保留,但若整个值是undefined,调用会报错)
绕过报错的实用策略
不能靠 try/catch 挽救,也不能给 structuredClone 加自定义序列化逻辑。真正有效的方式是提前干预数据结构:
-
预清洗对象:遍历源对象,删掉或替换掉不可克隆字段,例如把函数替换成字符串标识
{ onClick: 'handleClick' }或null -
提取可克隆子集:只构造你需要的字段再克隆,如
structuredClone({ id, name, items }),避开副作用字段 -
对特殊对象做序列化转换:比如
Date转toISOString(),RegExp转toString(),克隆后再还原 -
改用兼容性更强的第三方库:如
lodash.cloneDeep(支持函数占位、循环引用、自定义 handler),但需注意它不处理 DOM,也不保证 100% 安全无副作用
替代方案选型建议
根据场景选择更合适的工具:
- 纯数据对象(无函数、无 DOM、无循环)→ 直接用
structuredClone,性能好、零依赖 - 含方法/事件回调/类实例的业务对象 → 预处理 +
structuredClone,或用lodash.cloneDeep - 需跨旧环境运行(如 IE 或低版本 Node.js)→ 使用
@ungap/structured-clonePolyfill,但注意transfer等高级能力不可用 - Web Worker 通信且涉及大块二进制数据 → 结合
{ transfer: [buffer] }选项,实现零拷贝传输


















