structuredclone 仅在类构造函数可访问、实例无不可克隆字段、自有属性全为可结构化类型、原型无 getter/setter 时保留原型;含函数、symbol 键、闭包内类或不可枚举访问器则退化为 plain object。

structuredClone 对复杂自定义对象的原型处理有明确边界:它不主动克隆原型链,但对“可结构化”的自定义类实例,在满足条件时能保留其原型继承关系;本质上依赖对象是否符合结构化克隆算法(Structured Clone Algorithm)的可序列化要求。
哪些自定义对象能保原型?
只有同时满足以下条件的自定义类实例,structuredClone 才可能让 clone instanceof OriginalClass 仍为 true:
- 类构造函数在全局作用域或当前执行上下文中可访问(非闭包私有、未被删除)
- 实例本身不含不可克隆字段(如函数、Symbol 属性、undefined、DOM 节点)
- 所有自有属性值均为可结构化类型(Object、Array、Date、Map、Set、RegExp、ArrayBuffer 等)
- 原型链上不依赖 getter/setter 或不可枚举方法——这些不会被调用,也不会被复制
哪些情况会丢失原型?
以下情形下,克隆结果将退化为普通 plain object,instanceof 判断失败:
- 实例中包含任何函数(包括方法、箭头函数、class 内部方法)——直接抛 DataCloneError
- 使用 Symbol 作为属性键(整个键值对被跳过,可能导致关键逻辑缺失)
- 原型上定义了不可枚举属性或访问器(getter/setter),structuredClone 不执行它们,也不复制定义
- 类实例由闭包内定义的构造函数创建(如模块私有 class),克隆时无法重建对应原型
想真正保留完整原型行为?得手动干预
若业务强依赖原型方法(如 obj.format()、obj.validate()),仅靠 structuredClone 不够。可行路径是:
- 先用 structuredClone 拷贝数据部分(纯状态),再用 Object.create(OriginalClass.prototype) 创建新实例
- 将克隆后的数据属性逐个赋值到新实例上(注意过滤 constructor、不可枚举项)
- 对 Date、Map、Set 等内置类型,仍可复用 structuredClone 的安全拷贝能力,避免手写逻辑出错
- 若含函数,需单独提取逻辑、重新绑定,或改用策略模式/组合替代继承
更可持续的设计建议
与其强依赖原型链,不如转向更健壮的数据与行为分离方式:
- 把校验、格式化等逻辑抽成纯函数,接收 plain object 作为参数
- 用鸭子类型代替 instanceof 判断(例如检查是否有
format方法) - 在类设计阶段避免将关键状态存在不可克隆字段中(如用字符串代替 Symbol 标记)
- 对离线元数据、配置树等场景,优先用 structuredClone + schema 验证,而非运行时原型检查











