JS Intermediate

F.prototype и конструкторы

Понять, как function.prototype связывает конструктор и экземпляры, и как это работает «под капотом» классов.

Средний (Intermediate)

Кратко

Каждая функция имеет свойство prototype. Когда вы создаёте объект через new, его [[Prototype]] ссылается на constructor.prototype. Это связывает экземпляр с классом/конструктором.


Подробно

Что делает new?

new User('Анна') делает 4 вещи:

  • Создаёт новый пустой объект {}
  • Устанавливает его [[Prototype]] = User.prototype
  • Вызывает User.call(this, 'Анна') — constructor
  • Возвращает объект (если constructor не возвращает другой)

Связь: User.prototype === user.__proto__

Это значит:

  • Методы, определённые в User.prototype, доступны экземпляру
  • Изменение User.prototype влияет на все экземпляры

F.prototype vs Object.getPrototypeOf:

  • F.prototype — свойство функции (для нового экземпляра)
  • Object.getPrototypeOf(obj) — текущий прототип объекта

Важно:

  • F.prototype = {} — замена прототипа (осторожно!)
  • Object.create(proto) — создание с прототипом

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

F.prototype — как чертёж. new User() берёт чертёж User.prototype и создаёт дом. Все дома (экземпляры) используют один чертёж. Важно: это не копирование чертежа в каждый объект — объекты используют общий прототип для поиска свойств и методов.


Примеры

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

javascript
function User(name) {
  this.name = name;
}

User.prototype.greet = function() {
  return `Привет, ${this.name}`;
};

const user = new User('Анна');
console.log(user.greet()); // 'Привет, Анна'
console.log(user.__proto__ === User.prototype); // true

User.prototype становится прототипом экземпляра.

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

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} гавкает`;
};

const rex = new Dog('Рекс', 'овчарка');
console.log(rex.speak()); // 'Рекс гавкает'

Прототипное наследование через Object.create.

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

javascript
// class = синтаксический сахар:
// class User { greet() {} } 
// эквивалентно:
// function User(name) { this.name = name; }
// User.prototype.greet = function() {};

// Доказательство:
class User {
  constructor(name) { this.name = name; }
  greet() { return `Привет, ${this.name}`; }
}

const user = new User('Анна');
console.log(typeof User); // 'function'
console.log(User.prototype.greet); // function
console.log(user.__proto__ === User.prototype); // true

class — это function + prototype под капотом.


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

**Неправильно:** Забывать Dog.prototype.constructor = Dog

**Почему:** После Object.create() constructor ссылается на Animal, а не Dog.

**Правильно:** Восстанавливайте constructor: Dog.prototype.constructor = Dog.

**Неправильно:** Путать F.prototype и Object.getPrototypeOf

**Почему:** F.prototype — для нового экземпляра. getPrototypeOf — текущий прототип.

**Правильно:** F.prototype используется new. Object.getPrototypeOf — для чтения.

**Неправильно:** Менять F.prototype после создания экземпляров

**Почему:** Экземпляры уже ссылаются на старый prototype. Новые методы не будут доступны.

**Правильно:** Определяйте prototype ДО создания экземпляров.


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

  • new создаёт объект с [[Prototype]] = F.prototype
  • F.prototype — «чертёж» для экземпляров
  • Object.getPrototypeOf() — чтение текущего прототипа
  • class = function + prototype (синтаксический сахар)
  • Восстанавливайте constructor после Object.create()

Связь

Назад: Вы знаете цепочку прототипов (JI13) — теперь вы видите, как конструкторы с ней связаны.

Вперёд: Следующий урок (JI15) — встроенные прототипы: Array.prototype, Object.prototype.

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