JavaScript多态通过原型链动态查找方法实现:调用时从实例自身开始,沿__proto__向上搜索至Object.prototype,优先执行链上最先匹配的方法;构造函数继承中子类重写父类同名方法即体现多态;鸭子类型进一步放宽约束,只要对象有相应方法即可被统一处理。

JavaScript 中的多态性不靠类型声明,而是靠原型链在运行时动态查找方法来实现的。当你调用一个对象的方法时,引擎会先查对象自身,没找到就顺着 __proto__ 一路向上找,直到 Object.prototype,这个过程天然支持“同名方法、不同实现”的行为切换——这就是多态的核心。
原型链如何支撑多态行为
每个对象都有隐式原型(__proto__),指向其构造函数的 prototype 对象;而每个 prototype 对象本身也是普通对象,也有自己的原型,最终连成一条链。方法调用时的查找路径决定了谁的方法被真正执行:
- 如果子对象自身定义了
speak(),就用子对象的实现 - 如果没有,引擎自动沿原型链向上找,直到找到第一个匹配的
speak() - 哪怕父类和子类都定义了同名方法,也只调用链上最先命中(最靠近实例)的那个
通过构造函数继承实现方法重写
这是最典型的多态实践方式:子类覆盖父类方法,但调用接口保持一致。
例如:
function Animal(name) { this.name = name; }
Animal.prototype.speak = function() {
console.log(this.name + ' makes a sound');
};
function Cat(name, color) {
Animal.call(this, name);
this.color = color;
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
// ✅ 方法重写:同名方法,不同实现
Cat.prototype.speak = function() {
console.log(this.name + ' meows softly');
};
const myCat = new Cat('Luna', 'black');
myCat.speak(); // 输出 "Luna meows softly"
这里 myCat.speak() 不走 Animal.prototype.speak,因为 Cat.prototype 上已有同名方法,原型链在第一层就命中了——行为差异由实例所属的原型位置决定,而非声明时的类型。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
鸭子类型配合原型链增强多态灵活性
JavaScript 不强制对象属于某个类,只要它有需要的方法,就能被同一函数处理。原型链让这种结构兼容更自然:
- 你可以临时给对象挂载方法:
const duck = {}; duck.quack = () => console.log('Quack!'); - 也可以让多个无关构造函数共享同一原型方法(比如都指向
Swimmable.prototype) - 函数如
function makeItSpeak(animal) { animal.speak?.(); }完全不关心animal是哪个构造函数创建的,只看它“有没有speak”
注意原型链中断或覆盖导致的多态失效
多态依赖查找路径完整且可预期,以下情况会破坏它:
- 直接赋值
Cat.prototype = { speak() { ... } },会切断与Animal.prototype的连接,丢失继承链 - 忘记修复
constructor,虽不影响多态,但会让instance.constructor指向错误构造函数 - 用
Object.setPrototypeOf(obj, null)手动断开原型链,之后所有继承方法都无法访问
确保使用 Object.create(Parent.prototype) 或 class extends 来建立干净的原型继承关系,多态才能稳定生效。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










