JS Advanced

Прототипы: глубокое погружение

Разобрать prototype chain, Object.create, делегирование и конструкторы на уровне, превышающем базовый обзор из Intermediate.

Кратко

Прототипное наследование — каждый объект имеет ссылку [[Prototype]]. Object.create(proto) создаёт объект с явным прототипом. Prototype chain — цепочка поиска свойств: свойство → [[Prototype]] → [[Prototype]] → ... → null. Делегирование — когда методы определены на прототипе, а не на каждом экземпляре.


Подробно

Object.create(proto): const parent = { greet() { return Hello, ${this.name}; } }; const child = Object.create(parent); child.name = 'Анна'; console.log(child.greet()); // 'Hello, Анна'

child.greet не определён → поиск в parent → найден.

Prototype chain: child → parent → Object.prototype → null

Проверка цепочки: console.log(Object.getPrototypeOf(child) === parent); // true console.log(Object.getPrototypeOf(parent) === Object.prototype); // true console.log(Object.getPrototypeOf(Object.prototype) === null); // true

Делегирование (vs наследование): // Наследование: child НАСЛЕДУЕТ от parent // Делегирование: child ДЕЛЕГИРУЕТ родителю

const vehicle = { start() { console.log('Engine started'); }, stop() { console.log('Engine stopped'); } };

const car = Object.create(vehicle); car.drive = function() { console.log('Driving'); }; // car.start() → не найдено → delegation → vehicle.start()

Конструктор и prototype: function User(name) { this.name = name; } User.prototype.greet = function() { return Hi, ${this.name}; };

const user = new User('Анна'); // user → User.prototype → Object.prototype → null


Ментальная модель

Prototype chain — как цепочка рекомендаций. Вы спрашиваете: «Кто знает greet?» → «Я не знаю, но мой prototype знает» → «Я тоже не знаю, но мой prototype знает» → ... → «Никто не знает» (null). Object.create — как создать нового сотрудника с указанием его наставника.


Примеры

**Самый простой:**

javascript
const parent = { type: 'parent' };
const child = Object.create(parent);

console.log(child.type); // 'parent' (из прототипа)
console.log('type' in child); // true
console.log(child.hasOwnProperty('type')); // false
// type принадлежит parent, не child

Поиск свойств через prototype chain.

**Простой:**

javascript
function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function() {
  return `${this.name} makes a sound`;
};

function Dog(name) {
  Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  return `${this.name} barks`;
};

const rex = new Dog('Rex');
console.log(rex.speak()); // 'Rex makes a sound'
console.log(rex.bark()); // 'Rex barks'

Ручное наследование через прототипы.

**Реальный пример:**

javascript
// Делегирование для событий
const eventBus = {
  listeners: {},
  on(event, fn) {
    (this.listeners[event] = this.listeners[event] || []).push(fn);
  },
  emit(event, data) {
    (this.listeners[event] || []).forEach(fn => fn(data));
  }
};

const userEvents = Object.create(eventBus);
userEvents.on('login', (user) => console.log(`${user} logged in`));
userEvents.emit('login', 'Анна'); // 'Анна logged in'

// Делегирование: userEvents не определяет on/emit, но получает их от eventBus

Делегирование через Object.create для event bus.


Частые ошибки

**Неправильно:** Путать prototype и [[Prototype]]

**Почему:** prototype — свойство функции (constructor.prototype). [[Prototype]] — внутренняя ссылка объекта.

**Правильно:** prototype — у функции-конструктора. [[Prototype]] — у каждого объекта.

**Неправильно:** Думать, что наследование и делегирование — одно и то же

**Почему:** Наследование: child получает свойства parent. Делегирование: child ссылается на parent для поиска.

**Правильно:** Наследование = копирование. Делегирование = ссылка.

**Неправильно:** Забывать Object.create для delegation

**Почему:** Без Object.createprototype chain может быть нарушена ( например: Child.prototype = new Parent()).

**Правильно:** Используйте Object.create для явного создания цепочки.


Важно запомнить

  • Object.create(proto) — создание с прототипом
  • Prototype chain: object → parent → Object.prototype → null
  • Делегирование ≠ наследование
  • hasOwnProperty проверяет own properties
  • Конструктор + prototype = традиционное наследование

Связь

Назад: Вы знаете прототипы (JI13–JI16). Этот урок глубже разбирает внутреннее устройство цепочки и делегирование.

Вперёд: Следующий урок (JV7) — Proxy и Reflect — перехват операций над объектами.

Материалы курса JS Advanced — PROlab Academy.