structuredClone() 不支持 Error 对象,因规范明确排除其不可序列化的内部状态;应手动提取 name、message、cause、stack 等关键字段,用 new error.constructor() 重建实例,并在深拷贝中特判处理。

原生 structuredClone() 不支持 Error 对象,调用时会直接抛出 DataCloneError。这不是疏漏,而是规范明确排除——Error 实例包含不可序列化的内部状态(如堆栈跟踪、错误构造上下文),且其属性(stack、cause)行为不统一,强行克隆易导致语义失真或安全风险。
手动提取关键字段重建 Error 实例
最可控、兼容性最好的方式:不尝试“克隆”整个 Error,而是提取可安全复制的公开属性,新建一个同类型 Error。
- 读取
error.name、error.message、error.cause(若存在)和error.stack(注意:stack 是只读字符串,可复制但非实时更新) - 使用
new error.constructor(message)创建新实例,避免硬编码Error - 将
cause和自定义属性(如code、status)手动赋值到新实例上
封装为可复用的 deepClone 扩展逻辑
在自研深拷贝函数中加入 Error 类型特判,保持整体调用一致性:
- 检测
obj instanceof Error,命中则跳过递归,走重建逻辑 - 对
stack字段保留原值(不解析也不重生成),因为重生成的 stack 指向克隆函数本身,失去调试意义 - 若需保留
cause,对其递归调用 deepClone(前提是 cause 本身可被克隆)
避免踩坑的注意事项
有些做法看似方便,实则引入隐患:
- 用
JSON.stringify(error)→ 返回空对象{},丢失全部信息 - 直接
Object.assign({}, error)→ 得到普通对象,失去instanceof Error和原型方法(如toString()) - 试图遍历并复制所有 ownProperty → 大量不可枚举、不可写属性(如
stack)无法赋值,且不同浏览器实现差异大
本质上,Error 不是数据容器,而是运行时异常载体。优雅支持它的关键不是“完美复制”,而是“保真重建”——保留可观察、可传递、可调试的核心语义,其余细节主动舍弃。

















