javascript的多态依靠原型链查找和运行时方法绑定实现,包括方法重写、鸭子类型和动态绑定三种形式,本质是动态多态而非编译时类型系统保证。

JavaScript 中的“多态”不是靠编译时类型系统保证的,而是靠原型链查找 + 运行时方法绑定自然达成的。只要调用时对象身上(或其原型链上)存在同名方法,就会执行那个版本——这本身就是动态多态。
方法重写:子类覆盖父类同名方法
这是最直观体现多态的方式。子构造函数或 class 的原型上定义与父类同名的方法,实例调用时自动走子类实现,无需显式判断类型。
- 使用
Object.create(Animal.prototype)设置子类原型,再在子类原型上定义speak(),就完成了对父类speak()的重写 - ES6 中用
class Dog extends Animal+override speak()更简洁,底层仍是原型链操作 - 关键点:方法查找从实例自身开始,逐级向上遍历原型链,最先找到的那个
speak就被调用
鸭子类型:不依赖继承,只看有没有对应方法
只要对象有某个方法名,就能被统一函数处理。这种结构匹配才是 JavaScript 多态最轻量、最常用的形式。
一款AI工具,主要用于使用 OpenAI Codex CLI 处理编码任务。触发词:codex、code review、fix CI、refactor code、implement feature、coding agent、gpt-5-codex。Clawdbot 可将编码工作委托给 Codex CLI 作为子代理或直接工具,适合需要提升相关任务效率的用户。
- 比如
function perform(action) { action.run(); },传入{ run() { console.log('car'); } }或{ run() { console.log('robot'); } }都能正常运行 - 不需要
instanceof判断,也不需要共享父类,只要“会 run”,就被视为合法参数 - 适合插件化、策略模式等场景,新增行为不用改调用方代码
动态绑定:方法调用在运行时才决定执行谁
JS 不会在定义时锁定方法归属,而是在每次调用时实时查找。这意味着你可以中途替换原型上的方法,影响所有已有实例的行为。
- 修改
Dog.prototype.speak = function() { ... }后,之前创建的new Dog()实例下次调用speak()就会执行新逻辑 - 甚至可以临时给单个实例挂载方法:
myDog.speak = function() { ... },它会优先于原型链上的同名方法 - 这种灵活性是静态语言不具备的,也是 JS 多态更“动态”的核心原因
避免常见误区:别混淆属性和方法的查找机制
原型链只用于方法和可继承属性的查找;实例自身属性(如 this.name)不会被原型上的同名属性覆盖,也不会沿链查找。
- 如果父类构造函数里写了
this.type = 'animal',子类没覆盖,那每个实例都有自己的type属性,互不影响 - 但
this.speak()调用时,引擎会忽略实例自身的speak(除非真有),转而查原型链 - 理解这个区别,才能准确预测“哪个 speak 被执行”、“哪个 type 被读取”










