javascript原型链通过运行时动态查找方法实现多态:引擎沿__proto__链逐级向上搜索同名方法,谁的原型上先定义就执行谁的,从而支持继承重写和鸭子类型两种方式,es6 class仅为底层原型机制的语法糖。

原型链机制支持多态,靠的是运行时动态方法查找——调用一个方法时,JavaScript 引擎不会看对象“属于什么类型”,而是顺着 __proto__ 链一层层往上找,直到找到第一个匹配的方法。不同对象只要在各自原型链上提供了同名但行为不同的实现,就能自然表现出“同一接口、不同行为”,这就是多态的本质。
原型链如何让多态成为可能
多态不依赖编译时类型声明,而依赖执行时的查找路径:
- 每个对象都有内部链接
[[Prototype]](通常通过__proto__访问),指向它的原型对象 - 当调用
obj.method()时,引擎先查obj自身,再查obj.__proto__,再查obj.__proto__.__proto__,依此类推 - 谁的原型上先定义了该方法,就执行谁的——这使得子类可以“覆盖”父类方法,实例调用时自动命中最近的那个版本
- 链的终点是
Object.prototype,其__proto__为null,查找失败则返回undefined
两种主流的多态实现方式
JavaScript 的多态不绑定继承关系,灵活且轻量:
-
继承重写式多态:通过原型链建立父子关系,子构造函数共享父原型,再在子原型上定义同名方法。例如
Dog.prototype.speak覆盖Animal.prototype.speak,new Dog().speak()就执行狗的叫声 -
鸭子类型式多态:完全不依赖
extends或Object.create。只要多个对象都有.render()方法,函数function draw(item) { item.render(); }就能统一处理它们——结构一致即视为兼容
ES6 class 只是语法糖,底层仍是原型链
class 写法看着像 Java,但编译后还是操作 prototype 和 __proto__:
-
class Dog extends Animal等价于设置Dog.prototype.__proto__ = Animal.prototype -
super()实际是调用父构造函数,super.method()是显式从父原型取方法 - 即便用 class,依然可以运行时修改
Dog.prototype.speak,改变所有已有和未来实例的行为
容易踩坑的关键细节
多态表现是否正常,取决于原型链是否按预期构建:
- 如果先给
Student.prototype添加方法,再执行Student.prototype = new Person(),之前加的方法会丢失——因为原型引用已重置 -
constructor属性不会自动更新,重设原型后需手动补上:Student.prototype.constructor = Student - 箭头函数没有
prototype,不能当构造函数使用,也不参与原型链继承
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











