structuredclone不能真正克隆error对象,仅将其降级为普通对象:保留message、name等可枚举属性,丢失原型链、instanceof关系、tostring等方法及不可枚举属性(如部分cause、动态stack)。

structuredClone 能拷贝 Error 对象,但只保留可枚举属性,不保留原型链和方法。它会把 Error 实例当作普通对象处理:将 message、name、stack(如果可枚举)等自有属性复制为字符串或基础值,但不会重建 Error 构造函数,也不会保留 instanceof Error 关系或任何原型上的行为(如 .toString() 的特殊逻辑)。
Error 对象被 structuredClone 后的实际表现
拷贝后的对象是一个 plain object,不是真正的 Error 实例:
-
structuredClone(new Error('oops')).constructor === Object→true -
structuredClone(new Error('oops')) instanceof Error→false -
structuredClone(new Error('oops')).message→ 正常返回字符串"oops" -
structuredClone(new Error('oops')).stack→ 若原 Error 的stack是可枚举属性(多数浏览器默认是),则会被复制为字符串;否则可能丢失
哪些 Error 相关内容会丢失
以下特性在克隆后不可用或失效:
- 原型方法:如
.toString()、.toJSON()不再存在 - 自定义属性若通过
Object.defineProperty设置为不可枚举,则不会被复制 - 非标准属性(如
cause)——部分浏览器支持,但 structuredClone 是否保留取决于该属性是否可枚举且属于可克隆类型;cause若是另一个 Error,其本身也会被降级为 plain object - 堆栈跟踪的动态性:克隆得到的
stack字符串是原 Error 创建时的快照,不会随克隆体使用位置变化
替代方案建议
若需保持完整的 Error 行为,不要依赖 structuredClone:
- 传递 Error 时优先用引用(如日志、错误边界中直接抛出原对象)
- 需要序列化传输时,手动提取关键字段:
{ name, message, stack, cause: error.cause && serializeError(error.cause) } - 在支持环境(如现代浏览器),可用
new Error(clone.message)重建实例,并手动赋值error.name和error.stack = clone.stack(注意 stack 可读不可写,需用Error.prepareStackTrace或其他方式模拟,实际中通常只保留 message 和 name)
与其他不可克隆类型的对比
Error 属于“部分支持”类型——它不会像 function、Promise、WeakMap 那样直接抛 DataCloneError,而是静默降级为普通对象。这种行为容易被忽略,导致后续代码调用 .stack 没问题,但 err instanceof Error 或 err.toString() 失败。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











