← Назад к вопросам

Что происходит при обращении к методу объекта который есть только у родителя?

2.0 Middle🔥 181 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Концепция прототипного наследования и поиска методов

При обращении к методу объекта, который существует только в родительском объекте (в контексте JavaScript — в его прототипе), происходит процесс цепочки поиска в прототипной цепи (prototype chain).

Механизм поиска метода

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

  1. Проверка самого объекта — Сначала движок проверяет, существует ли запрашиваемое свойство или метод непосредственно в самом объекте. Если он их находит, он сразу их использует.
  2. Переход к прототипу — Если свойство или метод не найдены в объекте, движок автоматически переходит к его прототипу (__proto__ или Object.getPrototypeOf()), то есть к объекту, который был указан как родительский (например, в свойстве prototype функции-конструктора).
  3. Поиск в прототипе родителя — Движок повторяет поиск в этом родительском объекте. Если метод находится там — он вызывается. Важно: при вызове метод получает контекст (this) оригинального объекта, который инициировал поиск, а не родительского прототипа.
  4. Продвижение по цепочке — Если метод не найден и в этом прототипе, процесс повторяется: движок переходит к прототипу прототипа (прототипу родителя). Цепочка продолжается до достижения базового объекта (Object.prototype).
  5. Результат поиска — Если после всего поиска свойство не найдено, возвращается undefined. Для метода это приведет к ошибке TypeError: someObj.method is not a function.

Практический пример

Рассмотрим классический пример наследования через функции-конструкторы.

// Родительский "класс"
function Animal(name) {
    this.name = name;
}

// Метод добавлен в прототип родителя
Animal.prototype.sayHello = function() {
    console.log(`Hello, I'm ${this.name}`);
};

// Дочерний "класс"
function Dog(name, breed) {
    // Вызов конструктора родителя для инициализации общих свойств
    Animal.call(this, name);
    this.breed = breed;
}

// Ключевой шаг: установка прототипной связи
Dog.prototype = Object.create(Animal.prototype);
// Корректировка конструктора в прототипе для дочернего объекта
Dog.prototype.constructor = Dog;

// Специфичный метод только для Dog
Dog.prototype.bark = function() {
    console.log('Woof!');
};

// Создание экземпляра
const myDog = new Dog('Rex', 'Labrador');

// Вызов метода, который есть только у родителя
myDog.sayHello(); // Что здесь происходит?

Что происходит при вызове myDog.sayHello():

  • Движок проверяет, есть ли метод sayHello непосредственно в объекте myDog. Его нет.
  • Движок переходит к прототипу myDog, то есть к Dog.prototype. Метода sayHello там также нет (там есть только bark).
  • Движок переходит к прототипу Dog.prototype, который был установлен как Object.create(Animal.prototype). Теперь он проверяет Animal.prototype.
  • В Animal.prototype метод sayHello найден.
  • Метод вызывается с контекстом this, установленным в исходный объект myDog. Поэтому в консоли выводится: "Hello, I'm Rex".

Ключевые особенности и важные замечания

  • Контекст (this) — При успешном поиске метода в прототипе он вызывается в контексте оригинального объекта-инициатора. Это обеспечивает корректную работу с данными, хранящимися в этом объекте, даже если метод физически расположен "выше" в цепочке.
  • Переопределение (overriding) — Если в дочернем объекте (например, в Dog.prototype) будет добавлен свой метод с именем sayHello, он "затенит" (override) метод из родительского прототипа. Поиск остановится на первом найденном совпадении.
  • Современная альтернатива — В ES6+ для организации подобной логики чаще используются классы (class и extends), которые представляют собой "синтаксический сахар" над описанной прототипной моделью, но механизм поиска остается абсолютно идентичным.
  • Производительность — Длинные прототипные цепочки могут теоретически влиять на производительность, так как поиск требует последовательных шагов. Однако для большинства практических случаев это не является проблемой.

Таким образом, обращение к методу родительского объекта — это фундаментальный и мощный механизм JavaScript, реализующий наследование и делегирование через динамический поиск в иерархической цепочке прототипов.

Что происходит при обращении к методу объекта который есть только у родителя? | PrepBro