javascript中class不是复用源头而是封装工具,真正复用依赖组合优先、原型方法共享、语义化继承及抽象契约;应避免过度继承,善用mixin、实例注入和模板方法模式。

JavaScript 中 class 语法本身不是“复用”的源头,而是封装和组织复用逻辑的工具。真正支撑代码复用的,是背后的设计原则与实践方式——这些原则不依赖语法糖,但在 class 结构中更易落地、更易协作。
优先组合而非继承
ES6 的 class 容易让人误以为“必须用 extends 才算复用”,但实际工程中,过度继承会增加耦合、降低可测试性。更稳健的做法是把可复用行为抽成独立类或普通对象,再通过实例属性或方法注入。
- 比如通用数据校验逻辑,不必让每个业务类都继承
Validator,而可定义const validator = new Validator(),然后在业务类中调用this.validator.validate(...) - 混入(mixin)模式也属组合:把
EventEmitter、Serializable等能力以对象方式“叠加”到目标类实例上,避免单继承链断裂
封装公共状态与行为于原型
class 声明的方法默认挂载在原型上,这是 JavaScript 天然支持高效复用的关键机制。只要方法不依赖闭包中的私有变量,就该放在原型而非构造函数内。
- 错误写法:
constructor() { this.render = () => { ... } }→ 每个实例都新建函数,浪费内存 - 正确写法:
render() { ... }→ 所有实例共享同一函数引用,1000 个实例仅占用 1 份内存 - 属性仍需在
constructor中初始化(如this.items = []),避免多个实例意外共享引用类型数据
用 extends 解决“是…的一种”关系
继承只应在语义明确的层级关系中使用,例如 AdminUser extends User、Circle extends Shape。此时 class 的 extends + super 提供了清晰的契约:
- 子类能自然复用父类已验证的初始化逻辑(
super())、公共方法(super.save())和 getter/setter - 父类可预留钩子(如
beforeSave()),由子类选择性覆盖,实现“模板方法”模式 - 注意修复
constructor的prototype.constructor指向(Child.prototype.constructor = Child),否则 instanceof 和反射可能出错
抽象共性,延迟具体实现
JavaScript 没有原生抽象类,但可通过约定和运行时检查模拟其意图:在基类中定义方法骨架,要求子类实现特定方法。
- 例如基类
Renderer中写render() { throw new Error('子类必须实现 render'); } - 配合 JSDoc 标注
@abstract或 TypeScript 接口约束,提前暴露复用边界 - 这种“契约式复用”比硬编码逻辑更灵活,也便于单元测试时用 mock 类替代
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











