Какой метод вызывается при наследовании, если метод определён в прототипе родителя и в экземпляре дочернего класса в JavaScript
Что проверяют
Понимаете ли вы, как JavaScript ищет свойство, и не переносите ли туда модель Java один в один. В Java метод выбирается по классу объекта через виртуальную диспетчеризацию, а в JS есть только свойства и цепочка прототипов. Следом обычно спрашивают, как вызвать родительскую версию и что изменится со стрелочной функцией в поле класса.
Как отвечать
Вызовется метод экземпляра. Поиск свойства начинается с собственных свойств объекта, потом идёт Child.prototype, потом Parent.prototype, потом Object.prototype, и заканчивается на null. Вызывается первое найденное свойство, остальные затеняются (shadowing).
Разложите, где что живёт:
- метод класса
greet() {}: лежит на прототипе, один на все экземпляры; - поле класса
greet = () => {}: как и присваиваниеthis.greet = ...в конструкторе, создаёт собственное свойство у каждого экземпляра; - проверка:
Object.hasOwn(obj, "greet")покажет, собственное ли свойство, аdelete obj.greetснова откроет метод прототипа.
Отсюда ответ: если родитель объявил greet на прототипе, а в дочернем классе метод записан в экземпляр, работает экземплярная версия. Причём она перекроет и метод в Child.prototype, если такой есть.
Для собеседования полезнее всего обратная ловушка: родитель объявил greet = () => {} полем, а наследник переопределил greet() обычным методом. Выиграет поле родителя, потому что оно собственное, а метод наследника лежит в прототипе. Для разработчика на Java это выглядит как сломанное переопределение, но в JS поиск работает именно так.
super.greet() ищет метод в прототипе родителя, поэтому достаёт только методы прототипа, а не поля экземпляра.
Где спотыкаются
Отвечают «вызовется метод дочернего класса, потому что он переопределён», не различая прототип и экземпляр. Для этого вопроса это ключевое различие.
Думают, что стрелочная функция в поле ведёт себя как метод класса. Она создаётся заново для каждого объекта, не переопределяется методом наследника и недоступна через super.
Проводят прямую аналогию с Java и говорят про перегрузку. В JS нет перегрузки по сигнатуре: второе объявление с тем же именем просто заменяет первое.