通用原型链完整复制函数需同时建立原型继承关系和手动继承静态属性:先用object.create设置子类原型并修正constructor,再用object.setprototypeof建立静态继承链,并递归拷贝父类及其整个静态原型链上的自有属性(过滤内置属性),同时兼容公共静态字段、忽略私有静态成员、处理symbol属性和装饰器元数据。

要实现通用的原型链完整复制函数,关键不是“复制”,而是正确建立子类与父类之间的原型继承关系,并手动继承静态属性。JavaScript 的 class 语法本身不自动继承父类静态成员(如静态方法、静态字段),必须显式处理。
确保原型链完整:Object.setPrototypeOf + 构造函数绑定
仅靠 Child.prototype = Object.create(Parent.prototype) 不够,还需修复 constructor 指向,并用 Object.setPrototypeOf 确保 Child.__proto__ 正确指向 Parent,从而支持静态属性的继承链查找。
- 设置子类原型为父类原型的副本:
Child.prototype = Object.create(Parent.prototype) - 修正构造函数:
Child.prototype.constructor = Child - 建立静态继承链:
Object.setPrototypeOf(Child, Parent)
手动继承所有层级静态属性(含多级父类)
静态属性不会沿 __proto__ 自动继承(ES2022 前),需遍历父类及其整个静态原型链(Parent → Parent.__proto__ → … → Function.prototype),跳过内置不可枚举属性,只拷贝自有、可枚举/不可枚举的静态成员。
- 用
Object.getOwnPropertyNames获取父类所有自有属性名(含不可枚举) - 过滤掉
length、name、prototype等内置属性 - 用
Object.getOwnPropertyDescriptor获取描述符,再用Object.defineProperty安全定义到子类 - 递归处理
Parent.__proto__(若存在且不等于Function.prototype)
兼容 class 字段与私有成员的注意事项
静态公共字段(static x = 1)在实例化时才赋值,但定义时已作为自有属性存在于类上;静态私有字段(static #x = 1)无法被外部访问或复制,只能忽略——这是语言限制,不属于“未完美继承”,而是设计使然。
- 公共静态字段会被
getOwnPropertyNames捕获,正常复制 - 私有静态字段和方法无法反射获取,任何“复制”方案都无效,应避免依赖其跨类复用
- 装饰器添加的静态元数据(如 Reflect Metadata)需额外调用
Reflect.getOwnMetadataKeys处理
封装为可复用的 inherit 函数
将上述逻辑封装成函数,接收子类构造器和父类构造器,返回子类(便于链式调用),并支持多次继承(如 A ← B ← C)。
- 函数内部做空校验:
if (!(Parent instanceof Function)) throw - 执行原型链设置与静态属性继承
- 返回
Child,方便写法如class D extends inherit(C, B) {} - 可选支持 Symbol 属性:用
Object.getOwnPropertySymbols补充拷贝
不复杂但容易忽略细节。核心是两件事:原型链对齐 + 静态属性手动提升。只要这两步到位,子类就能自然访问父类所有层级的静态方法和字段,包括通过 super 在静态方法中调用父类同名静态方法。











