选型关键是“哪个缺陷你当前扛得住”;JavaScript继承核心矛盾是属性隔离与方法复用不可兼得;ES6 class+extends是默认选择,实为寄生组合式继承语法糖,自动规避原型链与构造函数硬伤。

选型关键不是“哪个最先进”,而是“哪个缺陷你当前扛得住”。JavaScript 继承的核心矛盾始终是:**属性隔离**和**方法复用**不可兼得——原型链保方法但共享引用属性,构造函数保属性但丢方法。现代项目中,直接手写继承已非常少见,但理解底层逻辑才能避开 runtime 崩溃、内存泄漏和调试黑洞。
优先用 ES6 class + extends(但得懂它在干啥)
这是绝大多数场景的默认选择,前提是目标环境支持(现代浏览器、Node.js ≥ 14)。它不是新机制,而是寄生组合式继承的语法糖,自动规避了原型链和构造函数各自的硬伤。
- 自动调用 super(),确保父类构造函数只执行一次,避免组合继承中父类被调两次的问题
- 子类 prototype 自动关联父类 prototype,方法天然复用,不重复创建
- 引用类型属性(如
this.items = [])在每个实例中独立,不共享 - 注意:必须在 constructor 中 先 super(),再访问 this,否则报
ReferenceError: Must call super constructor
需要兼容老环境?用寄生组合式继承(非 class 版)
当项目仍需支持 IE 或旧版 Node.js 时,这是目前最稳健的手写方案。它手动模拟了 class 的行为,绕开了原型链继承的引用共享和构造函数继承的方法丢失问题。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 核心操作:
Child.prototype = Object.create(Parent.prototype)—— 不用new Parent(),避免执行父类构造函数两次 - 补上
Child.prototype.constructor = Child,修复 constructor 指向 - 在子类构造函数里用
Parent.call(this, ...args)初始化实例属性 - 比“组合继承”少一次无意义的父类构造函数调用,性能和语义都更干净
纯工具类或配置对象?别继承,改用组合(Composition)
很多所谓“需要继承”的场景,其实只是想复用逻辑,而非建立 is-a 关系。强行继承反而引入耦合、破坏封装、增加测试难度。
立即学习“Java免费学习笔记(深入)”;
- 把通用能力抽成独立函数或类,通过参数传入或实例持有,例如:
class Logger { … }被UserService和PaymentService各自 new 一个,而不是让它们都继承 Logger - 使用 Mixin 模式(如
Object.assign(Target.prototype, Mixin1, Mixin2))横向复用方法,不改变原型链深度 - React 函数组件 + Hooks 就是典型组合实践:用
useEffect、useContext复用逻辑,而非继承 Component
警惕“伪继承”陷阱:instanceof 和 constructor 不等于真实关系
JS 中的继承是委托,不是复制。过度依赖 instanceof 判断类型,或误以为 constructor === Parent 就代表继承成功,容易在动态代理、装饰器、跨 iframe 场景下翻车。
-
instanceof依赖原型链上的constructor属性,而该属性可被随意修改 - 跨上下文(如 iframe)中,数组、正则等内置对象的原型不互通,
arr instanceof Array可能为 false - 更可靠的判断方式是:
Array.isArray()、Object.prototype.toString.call(arr) === '[object Array]',或检查实际行为(duck typing)

















