Получить имя суперкласса в ES6

У меня есть класс и еще один класс, который расширяет этот класс.

class Shape {
  constructor() {
    return this;
  }
}
class Circle extends Shape {
  constructor() {
    super();
    return this;
  }
}
let foo = new Circle();

Я могу получить класс foo с

let className = foo.constructor.name 
// returns string 'Circle'

Можно ли получить имя суперкласса foo ('Shape') аналогичным образом?

Ответ 1

Object.getPrototypeOf(Object.getPrototypeOf(foo)).constructor.name;

Ответ 2

Получил это:

let superClassName = foo.__proto__.__proto__.constructor.name
// return Shape

Изменить: это возвращает родительский класс, который не обязательно относится к классу Circle, который был первоначально выполнен. В моем случае использования они одинаковы, но здесь есть тонкая двусмысленность в отношении значения "суперкласса".

Ответ 3

Вы можете определить следующий класс:

class MyObject
{
  extends(className)
  {
    let next = Object.getPrototypeOf(this);

    while(next.constructor.name !== "Object")
    {
      if(next.constructor.name === className)
        return true;
      next = Object.getPrototypeOf(next);
    }
    return false;
  }
}

Пусть каждый определенный вами класс расширяет этот класс.

Теперь, если вы хотите проверить, расширяет ли ваш объект определенный класс, вы можете вызвать его как метод extends и передать в качестве аргумента имя родительского класса. Метод extends будет проходить по всему дереву наследования и проверять, расширяет ли ваш объект данный класс, проверяя не только его родителей, но также его бабушек и дедушек и бабушек и дедушек и т.д.

Пример:

class MyObject
{
  extends(className)
  {
    let next = Object.getPrototypeOf(this);

    while(next.constructor.name !== "Object")
    {
      if(next.constructor.name === className)
        return true;
      next = Object.getPrototypeOf(next);
    }
    return false;
  }
}

class Vehicle extends MyObject
{
}

class Car extends Vehicle
{
}

class Bmw extends Car
{
}

let car = new Car();
let bmw = new Bmw();

console.log("bmw extends Bmw: " + bmw.extends("Bmw"));
console.log("bmw extends Car: " + bmw.extends("Car"));
console.log("bmw extends Vehicle: " + bmw.extends("Vehicle"));
console.log("car extends Car: " + car.extends("Car"));
console.log("car extends Bmw: " + car.extends("Bmw"));

Ответ 4

Ваш конечный суперкласс всегда является Object, поэтому нет смысла пытаться его извлечь. Вам нужно выяснить, является ли рассматриваемый экземпляр экземпляром чего-то другого, используя ключевое слово 'is'. Я пишу это с точки зрения ActionScript-3, поэтому я не уверен, что такое синтаксис в ES-6, но он должен быть в строках "if (this Shape)". Это вернет true, если рассматриваемый экземпляр расширяет класс, о котором вы говорите, false в противном случае.

Однако то, что вы просите, - это то, где Shape отделяется от стандартной библиотеки или стандартного объекта, и компилятор или среда выполнения не могут понять это. Теоретически было бы неплохо, если бы языки ECMA могли дать вам задний массив наследования для данного класса, но AFAIK, который не является и никогда не был функцией. Без полной цепочки наследования вам нужно знать, какой суперкласс вы ищете, или вы не можете получить его каким-либо логическим способом.