通过Object.getPrototypeOf()获取源对象原型并用Object.create()创建副本,可重建原型链;需手动修复constructor或用Reflect.construct()确保instanceof一致;多层继承应递归设置或用structuredClone()。

直接用 Object.getPrototypeOf() 获取源对象的原型,再通过 Object.setPrototypeOf() 或构造函数重绑定,就能让副本继承原始原型链。关键不是“深拷贝属性”,而是“重建原型连接”。
获取并复用原始原型
调用 Object.getPrototypeOf(source) 得到源对象的原型(可能是 Object.prototype、自定义构造函数的 .prototype,甚至 null)。这个返回值可直接作为新对象的原型:
- 若源对象是普通对象:
const proto = Object.getPrototypeOf(obj); const copy = Object.create(proto); - 若源对象有自定义方法或访问器,仅用
{...obj}或JSON.parse(JSON.stringify())会丢失这些,必须靠Object.create(proto)启动原型链
处理构造函数与 instanceof 一致性
仅设原型还不够——copy.constructor 可能指向 Object,而非原始构造函数。需手动修复:
- 复制后执行
copy.constructor = source.constructor;(前提是source.constructor可信且存在) - 更稳妥的做法:用
Reflect.construct()模拟实例化,例如const copy = Reflect.construct(source.constructor, []); Object.setPrototypeOf(copy, Object.getPrototypeOf(source)); - 这样
copy instanceof source.constructor才返回true
应对多层原型链(如继承类实例)
如果源对象原型链较长(比如 class C extends B extends A 的实例),Object.getPrototypeOf() 只返回直接父原型。要完整还原,需递归设置:
- 先创建空对象
const copy = {}; - 用循环逐级获取并设置:
let proto = Object.getPrototypeOf(source); while (proto !== null) { Object.setPrototypeOf(copy, proto); proto = Object.getPrototypeOf(proto); }——但注意这会覆盖中间层,实际应从最顶层开始构建 - 推荐做法:用
Object.create()一次性传入最顶层原型,再逐级Object.assign()属性;或使用structuredClone()(现代环境)配合transfer选项(不适用原型链,但对ArrayBuffer等有效)
避开常见陷阱
动态还原原型链时容易踩坑:
-
不可对内置对象(如
Date、RegExp)直接设原型:它们的内部槽位([[DateValue]] 等)无法通过setPrototypeOf复制,需调用对应构造函数初始化 -
Object.setPrototypeOf()性能较低,避免在循环中频繁调用;优先用Object.create(proto)初始化 - 冻结/密封对象的原型不可修改,
setPrototypeOf会静默失败或抛错,需提前检查Object.isExtensible()和Object.getOwnPropertyDescriptor(obj, '__proto__')










