You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免JavaScript父类构造函数调用子类重写的方法?

问题解答

1. 你的操作没有错误,这是JavaScript类继承的正常行为

在ES6类的继承机制中,子类调用super()时,this已经绑定到子类实例上。因此父类构造器里调用的this.foobar()会优先匹配子类原型上的重写方法,这就是你看到输出B foobar的原因。

2. 几种更简便的解决方案

方案一:使用私有方法(推荐)

ES6私有方法(以#开头)仅能在父类内部访问,子类无法重写或调用,可彻底解决父类构造器方法被覆盖的问题:

class A {
  #foobar() { // 私有方法,子类无法访问
    console.log("A foobar");
  }

  constructor(x) {
    console.log("A constructor");
    this.x = x;
    this.#foobar(); // 调用父类私有方法
  }

  foobar() { // 对外暴露的公共方法,子类可正常重写
    this.#foobar();
  }
}

class B extends A {
  constructor(x, y) {
    console.log("B constructor");
    super(x);
    this.y = y;
  }

  foobar() {
    console.log("B foobar");
  }
}

let a = new A(123);
let b = new B(123, 456);

输出结果:

A constructor
A foobar
B constructor
A constructor
A foobar

方案二:直接调用父类原型上的方法

如果不想使用私有方法,可以在父类构造器中明确指定调用父类原型的方法,绕开子类的重写逻辑:

class A {
  constructor(x) {
    console.log("A constructor");
    this.x = x;
    A.prototype.foobar.call(this); // 直接调用父类原型方法
  }

  foobar() {
    console.log("A foobar");
  }
}

class B extends A {
  constructor(x, y) {
    console.log("B constructor");
    super(x);
    this.y = y;
  }

  foobar() {
    console.log("B foobar");
  }
}

let a = new A(123);
let b = new B(123, 456);

输出与方案一一致,父类构造器会执行A foobar。

方案三:抽离构造器专属逻辑为内部函数

把父类构造器需要执行的逻辑抽成独立的内部函数,不挂载到原型上,子类无法访问和重写:

class A {
  constructor(x) {
    console.log("A constructor");
    this.x = x;
    
    // 仅父类构造器可调用的内部函数
    function foobar() {
      console.log("A foobar");
    }
    foobar.call(this);
  }

  foobar() {
    console.log("A foobar");
  }
}

class B extends A {
  constructor(x, y) {
    console.log("B constructor");
    super(x);
    this.y = y;
  }

  foobar() {
    console.log("B foobar");
  }
}

let a = new A(123);
let b = new B(123, 456);

同样能实现父类构造器执行自身逻辑的效果。

内容的提问来源于stack exchange,提问作者TreeTownGreen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:27:14