← Назад к вопросам
Что происходит при обращении к методу объекта который есть только у родителя?
2.0 Middle🔥 181 комментариев
#JavaScript Core
Комментарии (1)
🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Концепция прототипного наследования и поиска методов
При обращении к методу объекта, который существует только в родительском объекте (в контексте JavaScript — в его прототипе), происходит процесс цепочки поиска в прототипной цепи (prototype chain).
Механизм поиска метода
Когда вы вызываете метод или пытаетесь получить свойство объекта, движок JavaScript выполняет следующие шаги:
- Проверка самого объекта — Сначала движок проверяет, существует ли запрашиваемое свойство или метод непосредственно в самом объекте. Если он их находит, он сразу их использует.
- Переход к прототипу — Если свойство или метод не найдены в объекте, движок автоматически переходит к его прототипу (
__proto__илиObject.getPrototypeOf()), то есть к объекту, который был указан как родительский (например, в свойствеprototypeфункции-конструктора). - Поиск в прототипе родителя — Движок повторяет поиск в этом родительском объекте. Если метод находится там — он вызывается. Важно: при вызове метод получает контекст (
this) оригинального объекта, который инициировал поиск, а не родительского прототипа. - Продвижение по цепочке — Если метод не найден и в этом прототипе, процесс повторяется: движок переходит к прототипу прототипа (прототипу родителя). Цепочка продолжается до достижения базового объекта (
Object.prototype). - Результат поиска — Если после всего поиска свойство не найдено, возвращается
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, реализующий наследование и делегирование через динамический поиск в иерархической цепочке прототипов.