Javascript ES6: как получить вызывающий подкласс из статического метода, определенного в суперклассе

Новое в JavaScript.

Нужны рекомендации о том, как получить доступ к имени вызывающего класса из статического метода, определенного в суперклассе с помощью классов ES6. Я потратил час на поиски, но не смог найти решение.

Фрагмент кода может помочь прояснить, что я ищу

class SuperClass {
    get callingInstanceType() { return this.constructor.name }
    static get callingClassType() { return '....help here ...' }
}

class SubClass extends SuperClass { }

let sc = new SubClass()

console.log(sc.callingInstanceType)     // correctly prints 'SubClass'
console.log(SubClass.callingClassType)  // hoping to print 'SubClass'

Как показано выше, я могу легко получить имя подкласса из экземпляра. Не совсем уверен, как получить доступ из статического метода.

Идеи по реализации static get callingClassType() приветствуются.


person So Over It    schedule 21.05.2017    source источник
comment
Вам будет трудно найти способ сделать это на любом языке. Поскольку статический метод не означает это, поэтому нет понятия вызывающего экземпляра.   -  person Kevin    schedule 21.05.2017
comment
Попробуйте return SuperClass.constructor.name;   -  person Derek    schedule 21.05.2017
comment
@ Дерек, это возвращает Function, а не SubClass. Есть ли способ проверить цепочку вызовов и выдернуть оттуда?   -  person So Over It    schedule 21.05.2017
comment
@Kevin Я понимаю, что нет вызывающего экземпляра. Мне было интересно, есть ли способ проверить цепь.   -  person So Over It    schedule 21.05.2017
comment
Во-первых, кажется излишним иметь такой метод. Пользователь уже знает имя класса, потому что использует его напрямую или как переменную. Вы можете просто сделать SuperClass.prototype.constructor.name и получить то, что вам нужно   -  person Derek    schedule 21.05.2017
comment
@Дерек. У меня есть логика в моем безумии относительно того, почему я хочу этого добиться. У него есть свое предназначение, но возможно ли это, в чем я не уверен.   -  person So Over It    schedule 21.05.2017
comment
@Kevin На самом деле в PHP это довольно просто: get_called_class(). И, как показывает ответ Феликса ниже, это выполнимо и в JS.   -  person Matt Browne    schedule 21.05.2017


Ответы (2)


callingClassType — это функция (ну, геттер в данном случае — то же самое). Значение this внутри функции зависит от того, как она вызывается. Если вы вызываете функцию с foo.bar(), то this внутри bar будет ссылаться на foo.

Таким образом, если вы «вызовете» функцию с помощью SubClass.callingClassType, this будет ссылаться на SubClass. SubClass сама по себе является функцией (конструктором), поэтому вы можете получить ее имя через свойство name.

Таким образом, ваше определение метода должно быть

static get callingClassType() { return this.name; }

class SuperClass {
  get callingInstanceType() {
    return this.constructor.name
  }
  static get callingClassType() {
    return this.name
  }
}

class SubClass extends SuperClass {}

let sc = new SubClass()

console.log(sc.callingInstanceType)
console.log(SubClass.callingClassType)

Посмотрите документацию MDN, чтобы узнать больше о this< /а>.

person Felix Kling    schedule 21.05.2017
comment
Потрясающий. Спасибо. Просто, когда знаешь как. - person So Over It; 21.05.2017

Используйте 1_:

class SuperClass {
    get callingInstanceType() { return this.constructor.name }
    static get callingClassType() { return SuperClass.prototype.constructor.name; }
}

class SubClass extends SuperClass {}
class SubClass2 extends SuperClass {
     static get callingClassType() { return SubClass2.prototype.constructor.name; }
}

console.log(SuperClass.callingClassType); // 'SuperClass'
console.log(SubClass.callingClassType); // 'SuperClass'
console.log(SubClass2.callingClassType); // 'SubClass2' 

Из https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static#Examples:

class Triple {
  static triple(n) {
    if (n === undefined) {
      n = 1;
    }
    return n * 3;
  }
}

class BiggerTriple extends Triple {
  static triple(n) {
    return super.triple(n) * super.triple(n);
  }
}

console.log(Triple.triple());        // 3
console.log(Triple.triple(6));       // 18

var tp = new Triple();

console.log(BiggerTriple.triple(3));
// 81 (not affected by parent's instantiation)

console.log(tp.triple());
// 'tp.triple is not a function'.
person Derek    schedule 21.05.2017
comment
Спасибо @Дерек. Но я хочу, чтобы SubClass.callingClassType возвращал SubClass, а не SuperClass - person So Over It; 21.05.2017
comment
Вам придется переопределить функцию в SubClass, чтобы получить это значение, потому что функция не является прототипом SubClass, если вы ее не добавите. - person Derek; 21.05.2017
comment
Я добавил пример SubClass2, который переопределяет метод. - person Derek; 21.05.2017