javascript多态依靠运行时原型链动态查找方法实现,支持继承重写和鸭子类型两种方式,es6 class仅为原型机制的语法糖。

JavaScript 中的多态不依赖编译时类型,而是靠运行时动态查找方法来实现。原型链正是支撑这一行为的核心机制——当调用一个方法时,引擎会沿着 __proto__ 链向上查找,直到找到第一个匹配的方法;不同对象可以提供同名但逻辑不同的实现,从而自然表现出“同一接口、不同行为”。
用原型链继承 + 方法重写实现多态
这是最贴近传统 OOP 多态的方式:子类继承父类原型,并覆盖(重写)同名方法。调用时,实际执行的是实例对应原型链上最近的那个版本。
- 定义父构造函数和原型方法,比如
Animal.prototype.speak = function() { console.log('makes a sound'); } - 子构造函数(如
Dog)通过Object.create(Animal.prototype)设置原型链,再将constructor指回自身 - 在子原型上定义同名方法(如
Dog.prototype.speak),即完成重写 - 创建
new Dog()和new Cat()实例,都调用.speak(),输出各自内容
鸭子类型:不依赖继承的多态
JavaScript 不强制要求继承关系。只要多个对象拥有同名方法,函数就能统一处理它们——这种结构一致性带来的多态更轻量、更灵活。
- 写一个通用函数,比如
function perform(action) { if (typeof action.run === 'function') action.run(); } - 传入
{ run() { console.log('car starts'); } }或{ run() { console.log('robot boots'); } } - 函数不关心对象是谁创建的,只检查是否有
run方法,有就调用
注意原型链查找的优先级
多态生效的前提是方法调用能正确命中目标实现。这取决于属性/方法在原型链中的位置:
- 实例自身定义的方法 > 子原型上的方法 > 父原型上的方法
- 若子类没重写
speak,就会沿链找到父类的版本,这不是多态失效,而是继承的默认行为 - 避免在子构造函数里用
this.speak = function() {...}覆盖——这样每个实例都带一份,失去共享和可维护性
ES6 class 是语法糖,本质仍是原型链
用 class Animal { speak() { ... } } 和 class Dog extends Animal { speak() { ... } } 写法更清晰,但底层仍通过修改 prototype 和 __proto__ 实现。Babel 编译后就是基于 Object.create 的原型操作,多态逻辑完全一致。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











