JS Intermediate

Прототипные методы и __proto__

Научиться работать с прототипами через Object.getPrototypeOf, Object.setPrototypeOf, и понять почему __proto__ — legacy.

Кратко

Object.getPrototypeOf(obj) — чтение прототипа (современный способ). Object.create(proto) — создание объекта с прототипом. __proto__ — legacy, избегайте в новом коде.


Подробно

Современные методы работы с прототипами:

  • Object.getPrototypeOf(obj) — чтение:

const obj = {}; console.log(Object.getPrototypeOf(obj) === Object.prototype); // true

  • Object.setPrototypeOf(obj, proto) — изменение:

const animal = { eats: true }; const rabbit = {}; Object.setPrototypeOf(rabbit, animal); console.log(rabbit.eats); // true

  • Object.create(proto) — создание:

const proto = { greet() { return 'Привет'; } }; const obj = Object.create(proto); console.log(obj.greet()); // 'Привет'

__proto__ — legacy: obj.__proto__ — это геттер/сеттер для Object.getPrototypeOf/setPrototypeOf

Почему __proto__ не рекомендуется:

  • Устаревший синтаксис
  • Может быть не реализован в некоторых средах
  • Медленнее
  • Путает с prototype (свойство функции)

Правило:

  • Читайте: Object.getPrototypeOf(obj)
  • Изменяйте: Object.setPrototypeOf(obj, proto)
  • Создавайте: Object.create(proto)
  • __proto__ — только для отладки

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

__proto__ — как старая карта. Она работает, но есть новая навигация (Object.getPrototypeOf). Используйте новую.


Примеры

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

javascript
const obj = {};
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true

const arr = [];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true

Object.getPrototypeOf показывает, откуда наследуются методы.

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

javascript
const animal = { eats: true };

// Создание с прототипом
const rabbit = Object.create(animal);
console.log(rabbit.eats); // true
console.log(Object.getPrototypeOf(rabbit) === animal); // true

Object.create — современный способ создания объекта с прототипом.

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

javascript
// Паттерн: mixin через Object.create
const Serializable = {
  serialize() {
    return JSON.stringify(this);
  }
};

const Loggable = {
  log() {
    console.log(this.toString());
  }
};

const user = Object.create(Serializable);
Object.assign(user, Loggable);
user.name = 'Анна';

console.log(user.serialize()); // '{"name":"Анна"}'

Object.create + Object.assign — mixin паттерн.


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

**Неправильно:** Использовать __proto__ в продакшен-коде

**Почему:** __proto__ — legacy. Может не работать в некоторых средах.

**Правильно:** Используйте Object.getPrototypeOf и Object.create.

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

**Почему:** __proto__ — свойство экземпляра (ссылка на прототип). prototype — свойство функции (чертёж).

**Правильно:** __proto__ === F.prototype для экземпляра, созданного через new F().

**Неправильно:** Использовать Object.setPrototypeOf для частых изменений

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

**Правильно:** setPrototypeOf — редко. Object.create — для первоначального прототипа.


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

  • Object.getPrototypeOf(obj) — чтение прототипа
  • Object.create(proto) — создание с прототипом
  • Object.setPrototypeOf — изменение (осторожно!)
  • __proto__ — legacy, избегайте
  • __proto__ === F.prototype для экземпляра new F()

Связь

Назад: Вы знаете встроенные прототипы (JI15) — теперь у вас есть инструменты для работы с ними.

Вперёд: Следующий урок (JI17) — полный набор методов массивов.

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