structuredclone 会因函数、undefined、symbol、promise、weakmap、weakset、proxy、generator、dom 节点、循环引用等不可序列化值抛出 data_clone_err 错误,它明确拒绝而非静默忽略;可行方案包括预处理对象、提取可克隆子集、使用 lodash.clonedeep 等第三方库,或对 date/regexp 转字符串再还原。

structuredClone 无法处理不可序列化对象(比如函数、undefined、Symbol、Promise、Date 对象本身虽可克隆但某些特殊 Date 实例可能出问题、DOM 节点、正则表达式等),遇到时会直接抛出 DATA_CLONE_ERR 错误。它不像 JSON.stringify 那样静默忽略,而是明确拒绝——这是设计使然,不是 bug。
哪些值会导致 structuredClone 报错
以下类型在调用 structuredClone 时会触发 TypeError: Failed to execute 'structuredClone' on 'Window': ... could not be cloned.:
- 函数(
function、箭头函数、class 方法) undefined-
Symbol(包括Symbol('a')) -
Promise、WeakMap、WeakSet、Proxy、Generator - DOM 元素、window、document 等宿主对象
- 带有循环引用的对象(即使全是可克隆类型,也会报错)
绕过报错的实用方法
不能靠 try/catch “修复” structuredClone,它不支持自定义序列化逻辑。真正可行的思路是:**提前清理或替换不可克隆字段**。
-
手动预处理对象:遍历对象,删掉或替换掉函数、undefined、Symbol 等字段。例如把函数转为
null或字符串标识:{ onClick: 'handleClick' } -
用结构化子集克隆:只提取你需要的可克隆字段,构造新对象再 clone:
structuredClone({ id, name, items }) -
改用第三方深克隆库(如
lodash.cloneDeep或flatted):它们通过递归+类型判断+自定义 handler 支持更多类型,但注意安全边界(如不处理 DOM、不保证 100% 无副作用) -
对 Date/RegExp 等特殊对象,先转成可序列化形式:例如
date.toISOString()、reg.toString(),克隆后再还原
检测是否可被 structuredClone 的小技巧
没有内置的 canStructuredClone API,但可以快速试探:
function isCloneable(obj) {
try {
structuredClone(obj);
return true;
} catch {
return false;
}
}
⚠️ 注意:这个函数有副作用(执行一次 clone),仅适合开发调试或低频校验;生产中建议基于已知结构做白名单过滤,而不是运行时试探。
替代方案对比(何时不用 structuredClone)
如果数据里固定含函数或 Symbol,又必须保留语义,structuredClone 就不适用:
- 状态管理场景(如 Redux、Pinia):用 immer 或手写 reducer,避免深克隆
- 配置对象带回调?改成事件总线或依赖注入,而非克隆函数
- 需要克隆带方法的对象?考虑 class 实例 +
structuredClone(JSON.parse(JSON.stringify(obj)))(仅限纯数据),或实现toJSON方法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











