JavaScript方法查找严格遵循实例→子类prototype→父类prototype→Object.prototype的单向原型链,可用Object.getPrototypeOf()和hasOwnProperty()逐层定位;静态方法走类本身及构造器原型链,constructor被篡改需手动修复。

在复杂类层次结构中追踪方法来源和覆盖情况,关键不是“记住所有链路”,而是掌握查找路径和验证手段。JavaScript 的方法调用永远只走一条确定的原型链,不跳过、不合并、不回溯——只要理清实例 → 子类 prototype → 父类 prototype → Object.prototype 这条线,就能准确定位。
看实例的原型链走向
每个实例的方法查找起点是它的 __proto__,它一定指向构造该实例的类的 prototype 对象。比如:
class C extends B extends A,执行 const c = new C() 后:
c.__proto__ === C.prototypeC.prototype.__proto__ === B.prototypeB.prototype.__proto__ === A.prototypeA.prototype.__proto__ === Object.prototype
这就是实际运行时的查找路径。方法调用时,引擎严格按此顺序逐级检查,找到第一个定义了该方法的对象就停止。
查方法到底在哪定义
不用猜,直接用 Object.getPrototypeOf() 和 hasOwnProperty() 逐层检查:
立即学习“Java免费学习笔记(深入)”;
- 先查
C.prototype.hasOwnProperty('methodName'):返回 true 就说明是 C 自己定义的(覆盖了) - 否则查
Object.getPrototypeOf(C.prototype).hasOwnProperty('methodName'),即 B.prototype 上有没有 - 再往上查 A.prototype,最后查 Object.prototype
也可以写个简短函数辅助追踪:
function findMethod(obj, methodName) {<br> let current = obj;<br> while (current) {<br> if (current.hasOwnProperty(methodName)) return current;<br> current = Object.getPrototypeOf(current);<br> }<br> return null;<br>}
传入 C.prototype,就能返回该方法首次出现的位置对象。
区分实例方法和静态方法
静态方法(static method())完全不走实例原型链,它们挂在类本身上,查找路径是:C.method → C.__proto__.method → B.__proto__.method → Function.prototype.method
- 子类静态方法会遮蔽父类同名静态方法,但不会影响实例方法链
- 不能用
super.method()调用父类静态方法,必须显式写super.constructor.method()或直接用类名
警惕 constructor 指向被篡改
如果手动重设过 C.prototype = {...} 或用了 Object.assign(C.prototype, ...),可能丢失 constructor 属性,导致 C.prototype.constructor 不再指向 C。这虽不影响方法查找,但会让 instance.constructor 返回错误构造器,干扰调试和 instanceof 判断。
- 修复方式:
C.prototype.constructor = C - 更稳妥的做法:用
Object.create(Parent.prototype)设置原型,再补 constructor


















