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

JavaScript中调用其他实例父类方法的方案及优缺点分析

调用另一个实例的父类方法的可行方案

我构建了如下代码结构:

class Parent {
  constructor(id){
    this.id = id;
    this.partner = null;
  }
  fn(x) {
    console.log(`Parent:${this.id}:fn(${x})`);
  }
}

class Child extends Parent {
  constructor(id){
    super(id);
  }
  fn(x) {
    console.log(`Child:${this.id}:fn(${x})`);
    super.fn(x);
    console.log('  -> calling partner');
    // Trigger partner too (**** this is key line I'm asking about) 
    Object.getPrototypeOf(Object.getPrototypeOf(this.partner)).fn.call(this.partner, x);
  }
  setPartner(partner){
    this.partner = partner;
  }
}

a = new Child('a');
b = new Child('b');

a.setPartner(b);
b.setPartner(a);

a.fn('test a');
console.log('');
b.fn('test b');

在此场景中,类实例调用另一个实例的方法时,为避免无限循环,我直接调用了父类方法。我的问题是:是否存在其他合理的方式调用另一个实例的父类方法?

撰写问题时,我意识到通过拆分出_fn方法可以更简洁地解决底层问题,但仍希望了解调用父类方法的各类可行方案。另外我原本尝试使用__proto__.__proto__但未成功,也想知道是否可以通过super来实现类似super.fn.call(this, x)的调用。

拆分方法的代码如下:

class Parent {
  constructor(id){
    this.id = id;
    this.partner = null;
  }
  fn(x) {
    console.log(`Parent:${this.id}:fn(${x})`);
  }
}

class Child extends Parent {
  constructor(id){
    super(id);
  }
  _fn(x) {
      console.log(`Child:${this.id}:fn(${x})`);
      super.fn(x);
  }
  fn(x) {
      this._fn(x);
      console.log('   calling partner ->');
      this.partner._fn.call(this.partner, x);
  }
  setPartner(partner){
    this.partner = partner;
  }
}

a = new Child('a');
b = new Child('b');

a.setPartner(b);
b.setPartner(a);

a.fn('test a');
console.log('');
b.fn('test b');

可行方案汇总

  • 直接引用父类原型方法
    这是最简洁直观的方式,直接调用Parent.prototype.fn并通过call指定上下文:

    Parent.prototype.fn.call(this.partner, x);
    

    无需操作实例的原型链,直接明确指向父类的方法,可读性和维护性都很强。

  • 通过子类原型获取父类原型
    如果不想直接引用Parent类(比如模块化场景下父类未暴露),可以通过Child的原型来获取父类原型:

    Object.getPrototypeOf(Child.prototype).fn.call(this.partner, x);
    

    这种方式避免了两次调用Object.getPrototypeOf获取实例的原型链,效率更高。

  • 关于__proto__.__proto__的问题
    你之前尝试的__proto__.__proto__理论上是可行的,写法如下:

    this.partner.__proto__.__proto__.fn.call(this.partner, x);
    

    但__proto__是非标准属性(虽被主流浏览器支持),不推荐在生产环境使用,优先使用标准的Object.getPrototypeOf方法。

  • 关于super的使用限制
    不能通过super实现跨实例调用父类方法。super只能在类的方法内部使用,它的指向是当前类的父类原型,且上下文绑定的是当前实例,无法通过call/apply改变super的上下文指向,因此super.fn.call(this.partner, x)这种写法是无效的。

  • 拆分方法(推荐)
    你自己想到的拆分_fn方法的方案,是更优雅的工程化解决方案。它把业务逻辑和对外调用解耦,既避免了循环调用,也无需直接操作原型链,代码结构更清晰,维护成本更低,推荐在实际项目中优先使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 15:28:19