
在原型链继承中调用父类方法,核心是明确“谁的方法、在哪找、怎么调”,不能依赖 super(它只在 class 语法中有效),而要手动借助原型链和 call/apply 绑定 this。
确保子类原型正确指向父类实例
这是整个机制的前提。若跳过这步,子类实例根本找不到父类方法:
- 用
Child.prototype = new Parent()建立原型链,使子类实例的__proto__指向父类实例 - 必须重设
Child.prototype.constructor = Child,否则构造器指向会错乱 - 避免直接改写
__proto__或用this.__proto__.__proto__.method()—— 非标准且易被污染
在子类方法中显式调用父类原型方法
当子类重写了同名方法,又需要执行父类逻辑时,需手动调用:
- 推荐写法:
Parent.prototype.methodName.call(this, ...args) - 不推荐:
this.constructor.__proto__.methodName.call(this)(依赖内部属性,不稳定) - 若父类方法依赖
this上的属性(如this.name),call(this)是必须的,否则上下文丢失
避免共享引用属性带来的干扰
原型链继承会让所有子类实例共享父类原型上的方法——这本身是优点;但若父类构造函数中定义了引用类型属性(如数组、对象),它们会被所有子实例共用:
- 例如
this.colors = ['red']在Parent构造函数里,child1.colors.push('blue')会影响child2.colors - 解决办法:把实例属性放在构造函数内(用
call继承),把方法放在原型上(用原型链继承)——即组合继承
动态方法名调用需自行实现查找逻辑
如果方法名是变量(如 const methodName = 'validate'),无法用 super[methodName]()(语法错误),也不能靠原型链自动分发:
- 可封装工具函数,从
this.constructor.prototype开始,沿Object.getPrototypeOf向上遍历,直到找到该方法 - 或提前缓存父类原型:
const parentProto = Parent.prototype,再用parentProto[methodName].call(this) - 原生 JS 不支持类似 Java 的
super[expr](),这点必须接受并绕行











