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

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

Компании: циан, Rutube

Стек: JavaScript

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

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

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

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

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

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

В контексте классов (синтаксический сахар над прототипами):

  • Методы, объявленные в теле класса, попадают в ClassName.prototype.
  • Методы, объявленные в конструкторе через this.method = ..., становятся собственными свойствами экземпляра.

При вызове child.someMethod():

  • Если someMethod определён как собственное свойство экземпляра - вызывается он.
  • Если нет - поиск продолжается в ChildClass.prototype, затем в ParentClass.prototype.

Важно понимать: "переопределение" в экземпляре не изменяет прототип родителя. Оно лишь создаёт новое собственное свойство, которое "затеняет" метод из прототипа. Это поведение отличается от классического ООП, где переопределение метода в подклассе влияет на сам класс.

На практике

Этот механизм часто используется для:

  • Полиморфизма - экземпляр дочернего класса может вести себя по-разному, переопределяя методы родителя.
  • Декорации - вызов родительского метода через super.method() внутри собственного метода экземпляра.
  • Оптимизации - иногда методы специально выносят в экземпляр, чтобы избежать лишнего прохода по цепочке прототипов (хотя это редкость).

Однако стоит помнить о trade-off: создание методов в конструкторе для каждого экземпляра увеличивает потребление памяти, так как каждая функция создаётся заново. Методы в прототипе разделяются между всеми экземплярами.

Пример кода

JAVASCRIPT
class Parent {
greet() {
return 'Hello from Parent';
}
}
class Child extends Parent {
constructor() {
super();
// Собственный метод экземпляра, затеняет метод из прототипа
this.greet = function() {
return 'Hello from instance';
};
}
}
const child = new Child();
console.log(child.greet()); // 'Hello from instance'
// Проверка: метод в прототипе не изменился
console.log(Child.prototype.greet); // undefined (метод не определён в прототипе Child)
console.log(Parent.prototype.greet.call(child)); // 'Hello from Parent'
// Если убрать собственное свойство - будет вызван метод из прототипа
delete child.greet;
console.log(child.greet()); // 'Hello from Parent'

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

Начните с прямого ответа: вызывается метод из экземпляра. Затем объясните механизм цепочки прототипов и порядок поиска. Подчеркните разницу между "переопределением" в классическом ООП и "затенением" в JavaScript. Упомяните, что это поведение одинаково для классов и функций-конструкторов. Если спросят про super - поясните, что он позволяет явно вызвать метод родителя, даже если он затенён.

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

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

  • Понимание прототипного наследования, а не только синтаксиса классов.
  • Знание порядка поиска свойств в цепочке прототипов.
  • Умение объяснить разницу между собственными свойствами и свойствами прототипа.
  • Понимание последствий для памяти и производительности.
  • Способность связать теорию с практическими примерами.

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

  • Путаница с классическим ООП - кандидат говорит, что метод "переопределяется" в классе, хотя на самом деле создаётся новое свойство экземпляра.
  • Игнорирование цепочки прототипов - ответ "вызывается метод родителя" без учёта собственных свойств.
  • Непонимание super - утверждение, что super.method() всегда вызывает метод из прототипа родителя, даже если он затенён в экземпляре (на самом деле super работает с прототипом, но не с собственными свойствами экземпляра).
  • Забывают про delete - не упоминают, что удаление собственного свойства "открывает" доступ к методу из прототипа.

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

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