> Какой метод вызывается при наследовании, если метод определён в прототипе родителя и в экземпляре дочернего класса в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: НордКлан

Стек: JavaScript

> Пример ответа

Короткий ответ

При наследовании, если метод определён в прототипе родителя и в экземпляре дочернего класса, вызывается метод из экземпляра. JavaScript сначала ищет свойство в самом объекте, и только если его там нет - поднимается по цепочке прототипов. Это называется shadowing: собственное свойство экземпляра "затеняет" метод прототипа.

Подробное объяснение

Механизм разрешения свойств в JavaScript основан на цепочке прототипов. Когда вы обращаетесь к child.method(), движок выполняет следующие шаги:

  1. Проверяет собственные свойства объекта child (own properties). Если метод найден - вызывается он.
  2. Если не найден - переходит к Object.getPrototypeOf(child), то есть к Child.prototype.
  3. Если и там нет - продолжает подниматься по цепочке до Object.prototype и далее до null.

Важно понимать: при использовании class и extends методы, объявленные в теле класса, попадают в Child.prototype, а не в экземпляр. Но если вы присваиваете метод напрямую экземпляру (this.method = ... или child.method = ...), он становится собственным свойством и имеет приоритет.

Это поведение одинаково для ES6 классов и для классического прототипного наследования через Object.create или функции-конструкторы. Ключевой момент - порядок поиска: собственное свойство всегда выигрывает.

На практике

В реальной разработке этот механизм часто используется для переопределения поведения в конкретном экземпляре, не затрагивая другие экземпляры и сам класс. Например, для временной модификации метода в тестах или для реализации стратегий.

Однако стоит помнить о производительности: собственные свойства экземпляра замедляют доступ по сравнению с методами прототипа, так как движок должен проверять наличие собственного свойства перед переходом к прототипу. Для горячих путей лучше избегать shadowing.

Также важно не путать shadowing с переопределением метода в подклассе. Когда вы объявляете метод с тем же именем в class Child extends Parent, вы переопределяете его на уровне Child.prototype - это тоже shadowing, но на уровне прототипа, а не экземпляра.

Пример кода

JAVASCRIPT
class Parent {
greet() {
return 'Привет от родителя';
}
}
class Child extends Parent {}
const child = new Child();
console.log(child.greet()); // 'Привет от родителя' - метод из Parent.prototype
// Добавляем собственный метод экземпляру
child.greet = function() {
return 'Привет от конкретного экземпляра';
};
console.log(child.greet()); // 'Привет от конкретного экземпляра' - собственное свойство
const anotherChild = new Child();
console.log(anotherChild.greet()); // 'Привет от родителя' - не затронут
// Проверка цепочки
console.log(child.hasOwnProperty('greet')); // true
console.log(anotherChild.hasOwnProperty('greet')); // false

Как отвечать на собеседовании

Начните с прямого ответа: вызывается метод из экземпляра. Затем кратко объясните механизм цепочки прототипов: сначала собственные свойства, потом прототип. Упомяните термин shadowing. Если интервьюер попросит углубиться - расскажите про разницу между переопределением в подклассе и присваиванием экземпляру, приведите пример. Хорошо показать понимание, что class - это синтаксический сахар над прототипами.

Для уровня senior стоит добавить нюанс: собственные свойства экземпляра создают "скрытый класс" (hidden class) в V8, что может привести к деоптимизации. Это покажет глубокое понимание внутренностей движка.

Что проверяет интервьюер

Интервьюер оценивает:

  • понимание модели наследования в JavaScript, а не просто знание синтаксиса class;
  • умение объяснить механизм разрешения свойств через цепочку прототипов;
  • знание термина shadowing и его последствий;
  • способность отличить переопределение метода в подклассе от присваивания экземпляру;
  • для senior - понимание влияния на производительность и внутренние механизмы движков.

Типичные ошибки

  • Утверждение, что вызывается метод родителя - это неверно, если есть собственное свойство экземпляра.
  • Путаница между Child.prototype.method и child.method - это разные уровни цепочки.
  • Забывают, что методы класса не попадают в экземпляр автоматически, они живут в прототипе.
  • Думают, что super как-то влияет на разрешение - нет, super работает только внутри методов класса и не меняет порядок поиска для обычных вызовов.
  • Не учитывают, что присваивание метода экземпляру после создания объекта работает точно так же, как если бы метод был определён в конструкторе через this.method = ....

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью