结论:采用分层继承策略——底层用寄生组合式继承保兼容,中层用 class + extends 写业务,顶层靠工具链自动降级与 polyfill 注入;性能与兼容性需编译时、运行时、设计时协同实现。

直接说结论:不追求“一套规范”,而是用分层策略——底层用寄生组合式继承保兼容,中层用 class + extends 写业务,顶层靠工具链自动降级与 polyfill 注入。性能和兼容性不是非此即彼的选择题,是编译时、运行时、设计时三阶段协同的结果。
底层:寄生组合式继承仍是兼容性锚点
在需支持 IE9–10 或旧版安卓 WebView 的场景中,Object.create(Parent.prototype) 仍有风险(部分引擎未完全实现或存在原型污染隐患)。此时应采用经典中转函数方案:
- 用空函数
function F() {}作为原型中转,设F.prototype = Parent.prototype - 子类原型赋值为
new F(),再手动修正constructor - 全程不调用
Parent构造函数,避免副作用;也不拷贝属性,只建立原型链链接
中层:class 语法是现代开发的事实标准
class 不是替代原型,而是对寄生组合式继承的标准化封装。Babel 和 TypeScript 编译器已将其稳定转译为高性能 ES5 代码,V8 等引擎也做了深度优化(如内联缓存原型访问路径):
- 所有新业务逻辑、组件、工具类,统一用
class A extends B编写 - 禁止手动操作
__proto__或prototype.constructor,交由语法糖保障一致性 - 构造函数中仍可用
super()精确控制父类初始化时机,规避this提前访问问题
顶层:兼容性由构建链兜底,不侵入源码
向后兼容不该靠开发者写两套继承逻辑,而应由工程化手段隔离:
- 使用
@babel/preset-env按目标浏览器自动降级class,无需手写 ES5 继承片段 - 对关键基类(如全局 Store、EventEmitter)提供轻量 polyfill,仅在缺失环境注入,不影响现代环境执行路径
- 通过 ESLint 规则(如
no-class-assign、no-proto)+ TypeScript 类型检查,从源头拦截易错操作
关键避坑:性能陷阱不在继承本身,而在误用模式
真正拖慢速度的从来不是原型链查找,而是开发者无意识引入的冗余行为:
- ❌ 避免
Object.assign(Child.prototype, Parent.prototype)—— 这会扁平化方法,切断原型链,失去动态扩展能力 - ❌ 禁止在原型上挂载可变引用类型(如
arr = []),改用构造函数内初始化,防止实例间意外共享 - ✅ 接口级抽象优先:用
implements(TS)或 duck-typing 声明契约,降低继承深度,让“组合优于继承”落地为具体约束


















