Тонкости ключевого слова «супер» в javascript

#javascript #class #oop #inheritance #super

Вопрос:

У меня есть следующие два класса в javascript: Animals amp; Cat ( Cat расширяется Animal ). Оба класса будут иметь introduce() метод; однако Cat классу требуется некоторая дополнительная информация в этом методе. Поскольку я не хочу дублировать весь метод, я подумал о трех способах достижения этой цели.

Я описал три подхода в комментариях под методом introduct() в классе Cat.

  1. Первая версия не работает. Для меня это имеет смысл, потому что в нем используется неправильный контекст.
  2. Вторая версия действительно работает. Это также имеет смысл для меня, потому что я использую call() для явного задания контекста.
  3. Третья версия действительно работает. Для меня это не имеет смысла. Чем это отличается от первой версии? Изменяет ли super ключевое слово каким-то образом контекст?

Любая помощь будет признательна — спасибо!

 class Animal {
  constructor(name, age, legs, species, status) {
    this.name = name;
    this.age = age;
    this.legs = legs;
    this.species = species;
    this.status = status;
  }
  introduce() {
    return `Hello, my name is ${this.name} and I am ${this.age} years old and ${this.status}.`;
  }
}

class Cat extends Animal {
  constructor(name, age, status) {
    super(name, age, 4, 'cat', status);
  }

  introduce() {
    // return Animal.prototype.introduce()   ' Meow meow!';
    // return Animal.prototype.introduce.call(this)   ' Meow meow!';
    // return super.introduce()   ' Meow meow!';
  }
}
 

Комментарии:

1. » Чем это отличается от первой версии? «потому super что ключевое слово создано именно для такого сценария? На самом деле не имело бы смысла иметь его, если бы он на самом деле не работал ни для чего сложного.

2. @CRice Ну, super используется в других языках ООП для взаимодействия с родительским определением класса. Поэтому, если у вас есть someMethod(one) { super.someMerhod(one, "two"); } , вы бы вызвали родительскую версию метода. В этом примере кода необходимо обеспечить переопределение одного параметра, когда родитель принимает два параметра. Таким образом, в JS осталась та же семантика ООП, поэтому она не слишком отличается от традиционной ООП. В конце концов, class был введен для имитации традиционного ООП ближе. Так что, super.someMethod() это своего рода занятие this.__proto__.__proto__.someMethid.call(this) .

Ответ №1:

Третий подход является стандартным способом достижения этой цели. Функционально он такой же, как и 2-я версия. При вызовах формы super[method]() в качестве контекста задается текущий объект ( this ).

См. Документы MDN.