javascript面向对象以原型链为核心,原型继承适合共享不可变方法,组合用于隔离可变状态;组合继承融合二者,寄生组合继承优化为仅调用父构造函数一次。

JavaScript 的面向对象设计不依赖“类”本身,而是靠原型链实现行为复用。权衡原型继承与组合,核心在于明确:**什么该共享、什么该隔离;什么要动态可变、什么需实例独有**。
原型继承适合共享不可变行为
把所有实例共用的方法(比如 toString、save、validate)放在构造函数的 prototype 上,能节省内存、保证一致性。
- 方法只在原型上定义一次,所有实例通过
__proto__链访问,不重复创建函数对象 - 后续统一修改原型方法,所有已有实例立即生效(热更新友好)
- 适合工具型、无状态逻辑,如
Array.prototype.map、Date.prototype.toISOString
组合更适合封装可变状态和高内聚逻辑
当子类型需要独立的状态、私有数据或定制初始化流程时,硬套原型继承容易出问题——比如多个实例共享引用类型属性(数组、对象),造成意外污染。
- 在构造函数内部用
this.xxx = xxx初始化实例专属属性,避免原型上挂引用类型 - 通过调用父构造函数(
Parent.call(this, ...))来“借用”初始化逻辑,比单纯原型链更可控 - 组合常配合模块化设计,例如一个
Form实例内部组合Validator和Submitter对象,职责清晰、易于测试
组合继承是实际项目中最稳的选择
它不是二选一,而是把两者融合:用原型继承复用方法,用构造函数调用继承属性。这也是为什么它被称为“最常用”而非“最理想”的模式。
- 子类原型 = new 父类() → 继承父类原型上的方法
- 子类构造函数内执行
Parent.call(this, ...)→ 继承父类实例属性(尤其是字符串、数字、新对象等) - 记得修复
constructor指针:Child.prototype.constructor = Child
寄生组合继承进一步优化性能
组合继承有个小缺陷:父类构造函数会被调用两次(一次设原型,一次在子类中 call)。寄生组合继承用 Object.create(Parent.prototype) 替代 new Parent(),只调用一次父构造函数,且保持完整原型链。
- 避免了父类中可能存在的副作用(如发请求、改全局状态)被无意触发两次
- 原型链结构干净,
instanceof和isPrototypeOf行为完全正确 - 现代框架(如早期 React Class Component)和手写基类普遍采用此方式
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











