> Как работает прототипное наследование в JavaScript? (JavaScript)

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

Компании: Иннотех, циан, Soft_Media_Group, Kodix, Aston, IT-One, Rutube, Globaldrive, SmartWay, Яндекс

Стек: JavaScript

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

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

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

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

Прототипное наследование - фундаментальный механизм в JavaScript, реализованный через цепочку прототипов. Каждый объект имеет скрытое свойство [[Prototype]], которое ссылается на другой объект или null. При доступе к свойству объекта (например, obj.prop) движок сначала проверяет собственные свойства объекта, затем переходит по цепочке прототипов, пока не найдет свойство или не достигнет null.

Создание прототипной связи возможно несколькими способами:

  • Через конструкторы и new - функция-конструктор автоматически устанавливает prototype создаваемых объектов
  • Через Object.create(proto) - явное создание объекта с заданным прототипом
  • Через __proto__ (устаревший, но поддерживаемый) или современные Object.getPrototypeOf/Object.setPrototypeOf
  • Через классы ES6 - синтаксический сахар над прототипным наследованием

Ключевая особенность: прототипы - это живые объекты. Изменения в прототипе немедленно отражаются на всех наследующих объектах. Это позволяет реализовывать динамическое наследование и паттерн "mixin".

Важно понимать разницу между prototype (свойство функций-конструкторов) и [[Prototype]] (внутренняя ссылка объекта). У функций есть свойство prototype, которое становится прототипом для объектов, созданных через new.

На практике

В реальной разработке прототипное наследование используется для:

  • Создания иерархий объектов без дублирования кода
  • Реализации полиморфизма через переопределение методов в цепочке
  • Оптимизации памяти - методы хранятся в прототипе, а не копируются в каждый экземпляр
  • Расширения встроенных объектов (например, добавление методов в Array.prototype - но это антипаттерн в production)

Современный код чаще использует синтаксис классов ES6, но под капотом остается прототипное наследование. Понимание этого механизма критично для отладки, оптимизации и работы с фреймворками (React, Vue, Angular).

Пример кода

JAVASCRIPT
// Базовое прототипное наследование через конструктор
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
return `${this.name} издает звук`;
};
function Dog(name, breed) {
Animal.call(this, name); // вызов родительского конструктора
this.breed = breed;
}
// Устанавливаем прототипную связь
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// Переопределяем метод
Dog.prototype.speak = function() {
return `${this.name} (${this.breed}) лает`;
};
const rex = new Dog('Рекс', 'овчарка');
console.log(rex.speak()); // "Рекс (овчарка) лает"
console.log(rex instanceof Animal); // true
console.log(rex instanceof Dog); // true
// Современный эквивалент через классы
class AnimalES6 {
constructor(name) { this.name = name; }
speak() { return `${this.name} издает звук`; }
}
class DogES6 extends AnimalES6 {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() { return `${this.name} (${this.breed}) лает`; }
}

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

Начни с определения прототипного наследования как механизма связи объектов через [[Prototype]]. Подчеркни отличие от классического ООП: здесь нет классов, только объекты. Объясни цепочку прототипов и поиск свойств. Упомяни способы установки прототипа: Object.create, конструкторы, __proto__. Покажи понимание разницы между prototype и [[Prototype]]. Заверши примером с классами ES6 как синтаксическим сахаром. Будь готов обсудить производительность (поиск по цепочке) и нюансы (например, hasOwnProperty).

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

  • Понимание фундаментального механизма наследования в JS
  • Умение отличать прототипное наследование от классового
  • Знание внутренних механизмов: [[Prototype]], prototype, constructor
  • Способность объяснить цепочку прототипов и поиск свойств
  • Понимание современных паттернов (классы ES6) и их связи с прототипами
  • Глубина: знает ли кандидат о Object.create, setPrototypeOf, __proto__

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

  • Путаница между prototype (свойство функции) и [[Prototype]] (внутренняя ссылка объекта)
  • Утверждение, что классы ES6 - это не прототипное наследование
  • Забывание про constructor при ручной установке прототипа через Object.create
  • Использование __proto__ в production коде (лучше Object.getPrototypeOf/Object.setPrototypeOf)
  • Непонимание, что методы в прототипе общие для всех экземпляров (экономия памяти)
  • Ошибка в том, что this в методах прототипа ссылается на прототип, а не на экземпляр

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

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