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

Куда идет JavaScript если свойства нет в объекте?

2.2 Middle🔥 163 комментариев
#JavaScript Core#Браузер и сетевые технологии

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

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

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

Поиск свойства в JavaScript и цепочка прототипов

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

Основной механизм поиска

Процесс происходит по следующему алгоритму:

  1. Поиск в самом объекте: Движок сначала проверяет, существует ли свойство непосредственно в объекте (в его собственных свойствах).
  2. Переход к [[Prototype]]: Если свойство не найдено, движок обращается к внутреннему свойству объекта [[Prototype]] (которое доступно через Object.getPrototypeOf(obj) или через устаревшее, но известное свойство __proto__).
  3. Рекурсивный поиск по цепочке: Поиск продолжается в объекте-прототипе. Если свойство не найдено и там, движок переходит к прототипу этого прототипа, и так далее, пока не достигнет конца цепочки.
  4. Завершение поиска: Цепочка прототипов заканчивается на объекте null. Если свойство не было найдено на протяжении всей цепочки, результатом является undefined.

Пример цепочки прототипов

Рассмотрим классический пример с созданием объекта через функцию-конструктор.

// Функция-конструктор
function Animal(name) {
    this.name = name;
}

// Добавляем метод в прототип функции-конструктора
Animal.prototype.sayName = function() {
    console.log(`My name is ${this.name}`);
};

// Создаем экземпляр
const cat = new Animal('Whiskers');

// Попытка чтения свойства
console.log(cat.name); // "Whiskers" - свойство есть в самом объекте
console.log(cat.sayName()); // "My name is Whiskers" - метод найден в прототипе
console.log(cat.age); // undefined - свойство отсутствует в объекте и в цепочке прототипов

В данном случае:

  • Свойство name находится непосредственно в объекте cat.
  • Метод sayName находится в Animal.prototype. Движок не найдет его в cat, поэтому перейдет по ссылке [[Prototype]] объекта cat (которая равна Animal.prototype) и найдет метод там.
  • Свойство age отсутствует как в cat, так и в Animal.prototype. Поиск продолжится дальше: [[Prototype]] объекта Animal.prototype — это стандартный Object.prototype. Там этого свойства тоже нет. [[Prototype]] объекта Object.prototype равен null, поиск завершается, возвращается undefined.

Визуализация цепочки и технические детали

Цепочка для объекта cat выглядит так:

cat (экземпляр) → Animal.prototypeObject.prototypenull

Ключевые технические моменты:

  • Связь устанавливается при создании объекта: При использовании оператора new, свойство [[Prototype]] созданного объекта явно устанавливается в значение свойства prototype функции-конструктора.
  • Доступ через Object.getPrototypeOf(): Для получения прототипа объекта следует использовать современный метод Object.getPrototypeOf(obj). Свойство __proto__ является устаревшим геттером/сеттером для [[Prototype]].
  • Object.prototype — вершина для большинства объектов: Практически все объекты, созданные с помощью литерала {}, конструктора new Object() или через new с пользовательскими функциями, в конечном счете имеют Object.prototype в своей цепочке. Именно здесь находятся универсальные методы, такие как toString(), hasOwnProperty() и isPrototypeOf().
  • Разница между undefined и null в цепочке: Если в цепочке встречается свойство со значением undefined, это не остановит поиск. Поиск остановится только когда следующий прототип равен null.

Современная альтернатива: классы (ES2015)

Синтаксис классов в ES2015 является "синтаксическим сахаром" над существующей моделью прототипов, но делает работу с цепочкой более интуитивной.

class Animal {
    constructor(name) {
        this.name = name;
    }

    sayName() {
        console.log(`My name is ${this.name}`);
    }
}

const cat = new Animal('Whiskers');
console.log(cat.sayName()); // Метод находится в Animal.prototype

Методы класса автоматически помещаются в свойство prototype функции-конструктора класса. Таким образом, механизм поиска свойства остается абсолютно идентичным описанному выше.

Практическое значение для разработчика

Понимание цепочки прототипов критически важно для:

  • Эффективного использования наследования: Позволяет создавать иерархии объектов, экономя память (методы хранятся в прототипе, а не копируются в каждый экземпляр).
  • Понимания поведения объектов: Знание, где искать методы типа toString, помогает избежать ошибок.
  • Оптимизации производительности: Длинные цепочки прототипов могут негативно повлиять на скорость поиска свойства. В современных приложениях часто используют композицию вместо глубокого наследования.
  • Работы с полифилами (polyfills): Полифилы для новых методов языка (например, Array.prototype.flat) добавляются именно в объекты-прототипы (Array.prototype), чтобы они были доступны всем экземплярам через цепочку.

Таким образом, когда свойство отсутствует в объекте, JavaScript совершает переход по цепочке прототипов ([[Prototype]]) до объекта null. Этот механизм является основой для наследования, экономии памяти и организации кода в языке.

Куда идет JavaScript если свойства нет в объекте? | PrepBro