> Как обратиться к объекту и пройти по цепочке прототипов в JavaScript (JavaScript)

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

Компании: Сбер

Стек: JavaScript

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

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

Чтобы обратиться к объекту и пройти по цепочке прототипов в JavaScript, используй Object.getPrototypeOf(obj) для получения прототипа, а затем рекурсивно вызывай его, пока не получишь null. Альтернативно можно использовать __proto__ (не рекомендуется в production) или Reflect.getPrototypeOf. Цепочка заканчивается на Object.prototype, чей прототип - null.

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

Каждый объект в JavaScript имеет внутреннее свойство [[Prototype]], которое ссылается на другой объект или null. Это формирует цепочку прототипов, используемую для разрешения свойств и методов при обращении через точку или скобки.

Для программного обхода цепочки прототипов используй:

  • Object.getPrototypeOf(obj) - стандартный, безопасный способ, работает во всех современных средах.
  • Reflect.getPrototypeOf(obj) - аналог, часть Reflect API, возвращает тот же результат.
  • obj.__proto__ - устаревший геттер/сеттер, не рекомендуется из-за проблем с производительностью и совместимостью в некоторых edge-случаях.

Процесс обхода: начиная с объекта, получаем его прототип, затем прототип прототипа и так далее, пока не дойдём до null. Это позволяет инспектировать наследование, проверять наличие свойств в цепочке или копировать методы.

Важно: свойство constructor и методы вроде hasOwnProperty находятся в Object.prototype, поэтому они доступны всем объектам через цепочку.

На практике

На собеседовании senior-уровня ожидается не просто знание синтаксиса, а понимание внутреннего механизма и практических применений:

  • Проверка наследования: obj instanceof Constructor использует цепочку прототипов, но для прямого обхода лучше использовать isPrototypeOf.
  • Клонирование с сохранением прототипа: при создании объекта с тем же прототипом используй Object.create(Object.getPrototypeOf(obj)).
  • Полифиллы и метапрограммирование: обход цепочки нужен для реализации Object.assign с учётом прототипов или для создания глубоких копий.
  • Оптимизация: частый обход цепочки может быть медленным, поэтому для проверки собственных свойств используй hasOwnProperty.

Пример типичной задачи: написать функцию, которая собирает все ключи из цепочки прототипов, исключая встроенные методы Object.prototype.

Пример кода

JAVASCRIPT
// Функция для обхода цепочки прототипов
function walkPrototypeChain(obj) {
const chain = [];
let current = obj;
while (current !== null) {
chain.push(current);
current = Object.getPrototypeOf(current);
}
return chain;
}
// Пример использования
const parent = { a: 1 };
const child = Object.create(parent);
child.b = 2;
const protoChain = walkPrototypeChain(child);
console.log(protoChain); // [child, parent, Object.prototype, null]
// Проверка наличия свойства во всей цепочке
function hasPropertyInChain(obj, prop) {
let current = obj;
while (current !== null) {
if (prop in current) return true;
current = Object.getPrototypeOf(current);
}
return false;
}
console.log(hasPropertyInChain(child, 'a')); // true
console.log(hasPropertyInChain(child, 'toString')); // true (из Object.prototype)

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

Начни с чёткого определения цепочки прототипов и способов доступа к ней. Упомяни Object.getPrototypeOf как предпочтительный метод. Покажи понимание разницы между собственными и унаследованными свойствами. Приведи пример практического использования - например, для реализации глубокого сравнения объектов или для создания фабричной функции с наследованием.

Избегай излишнего углубления в детали реализации V8 или SpiderMonkey, если не спрашивают. Сфокусируйся на стандарте ECMAScript и практических сценариях.

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

  • Понимание механизма наследования через прототипы, а не классов (даже если используется синтаксис class).
  • Умение различать собственные и унаследованные свойства.
  • Знание стандартных API для работы с прототипами и их отличий.
  • Способность применять эти знания для решения реальных задач (клонирование, проверка типов, метапрограммирование).
  • Осознание trade-off между производительностью и удобством при обходе цепочки.

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

  • Использование __proto__ в production-коде без необходимости.
  • Путаница между prototype (свойство функции-конструктора) и [[Prototype]] (внутреннее свойство объекта).
  • Предположение, что Object.prototype всегда последний в цепочке - для объектов, созданных через Object.create(null), цепочка заканчивается на null сразу.
  • Забывание, что for...in проходит по всей цепочке, а не только по собственным свойствам.
  • Неправильная обработка null при рекурсивном обходе - отсутствие проверки приводит к ошибке.

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

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