是否可以访问 javascript class 层次结构中的所有级别?

Is it possible to access all levels in javascript class hierarchy?

所以我很好奇是否可以从基础(父)class 访问 class 层次结构中所有级别的静态属性。

我们来画个例子:

class Tier1 {
  static NUMBERS = ['one', 'two'];

  getNumbers() {
    // how to do here?
    return this.constructor.NUMBERS.join(', ');
  }
}

class Tier2 extends Tier1 {
  static NUMBERS = ['three'];
}

class Tier3 extends Tier2 {
  static NUMBERS = ['four', 'five'];
}

class Tier4 extends Tier3 {
  static NUMBERS = ['six'];
}

const t1 = new Tier1(); t1.getNumbers(); // Expect to get "one, two"
const t2 = new Tier2(); t2.getNumbers(); // Expect to get "one, two, three"
const t3 = new Tier3(); t3.getNumbers(); // Expect to get "one, two, three, four, five"
const t4 = new Tier4(); t4.getNumbers(); // Expect to get "one, two, three, four, five, six"

这种效果可以实现吗?我能否以动态方式从 this 向下遍历 class 实例层次结构?

希望在这里提供一些意见和想法

您可以通过在每个级别创建一个新的静态 NUMBERS 变量来完成此操作,该变量是前一个级别的副本并添加新项目,如下所示:

class Tier1 {
  static NUMBERS = ['one', 'two'];

  getNumbers() {
    return this.constructor.NUMBERS.join(', ');
  }
}

class Tier2 extends Tier1 {
  static NUMBERS = [...this.NUMBERS, 'three'];
}

class Tier3 extends Tier2 {
  static NUMBERS = [...this.NUMBERS, 'four', 'five'];
}

class Tier4 extends Tier3 {
  static NUMBERS = [...this.NUMBERS, 'six'];
}

const t1 = new Tier1(); console.log(t1.getNumbers()); // Shows "one, two"
const t2 = new Tier2(); console.log(t2.getNumbers()); // Shows "one, two, three"
const t3 = new Tier3(); console.log(t3.getNumbers()); // Shows "one, two, three, four, five"
const t4 = new Tier4(); console.log(t4.getNumbers()); // Shows "one, two, three, four, five, six"

或者如果您需要在每个 class 中有一个 separate NUMBERS 数组,并尽可能晚地组合它们(例如,因为它们的内容可能是可变的),那么你可以按照下面的方法。我认为这也回答了“我可以以动态方式从 this 向下遍历 class 实例层次结构吗?”肯定的“是”。

class Tier1 {
  static NUMBERS = ['one', 'two'];

  gatherAllNumbers() {
    const constructors = this.getConstructors();
    return constructors.reverse().map(c => c.NUMBERS).flat();
  }
  
  getConstructors() {
    const result = [];
    let next = Object.getPrototypeOf(this);
    while (next.constructor.name !== "Object")
    {
      result.push(next.constructor);
      next = Object.getPrototypeOf(next);
    }
    return result;
  }
  
  getNumbers() {
    return this.gatherAllNumbers().join(', ');
  }
}

class Tier2 extends Tier1 {
  static NUMBERS = ['three'];
}

class Tier3 extends Tier2 {
  static NUMBERS = ['four', 'five'];
}

class Tier4 extends Tier3 {
  static NUMBERS = ['six'];
}

const t1 = new Tier1(); console.log(t1.getNumbers()); // Shows "one, two"
const t2 = new Tier2(); console.log(t2.getNumbers()); // Shows "one, two, three"
const t3 = new Tier3(); console.log(t3.getNumbers()); // Shows "one, two, three, four, five"
const t4 = new Tier4(); console.log(t4.getNumbers()); // Shows "one, two, three, four, five, six"