Перейти к содержимому
Теория · Классы и прототипы · урок 1 из 12

Классы

Чему вы научитесь

Чему вы научитесь:

  • описывать объекты одного вида классом и создавать их через new;
  • вычислять свойство геттером, прятать данные в приватном поле # и создавать объекты статическим методом;
  • строить дочерний класс через extends и вызывать родителя через super;
  • объяснять, где лежат методы и как JavaScript ищет их по цепочке прототипов.
Чертёж стула User и два собранных по нему стула разного цвета с бирками ann и tom

Представьте мебельную фабрику. Инженер один раз рисует чертёж стула: какие у него ножки, сиденье и спинка, как его собрать. По этому чертежу цех собирает сотни стульев. Цвет у каждого свой, но устроены все одинаково.

В программе бывает так же: пользователей, товаров или заказов много, и у всех одни и те же свойства и действия. Функция, которая собирает объект из параметров, заново описывает его при каждом вызове: каждое свойство и каждый метод. Когда похожих объектов много, их общий вид удобнее описать один раз — классом. Класс — это чертёж, а объекты — стулья, собранные по нему:

JavaScript
class User {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    isAdult() {
        return this.age >= 18;
    }
}

const ann = new User("Ann", 30);
const tom = new User("Tom", 12);
console.log(ann.name, ann.isAdult()); // Ann true
console.log(tom.name, tom.isAdult()); // Tom false

Давайте разберём пример:

  1. class User { … } — чертёж: у каждого пользователя будут свойства name и age и метод isAdult.
  2. new User("Ann", 30) собирает по чертежу первый объект, а new User("Tom", 12) — второй.
  3. Первый console.log печатает Ann true: возраст ann — 30, а это не меньше 18.
  4. Второй печатает Tom false: тот же метод для tom отвечает иначе, ведь ему 12.

Класс и экземпляр

Класс описывает объекты одного вида: какие у них свойства и методы. Объект, созданный по классу, называют экземпляром: ann и tom — два экземпляра класса User. Имя класса по договорённости пишут с большой буквы.

Тело класса похоже на литерал объекта, но правила у него свои:

  • методы пишут без слова function;
  • между методами не ставят запятых;
  • метод с именем constructor заполняет каждый новый объект.

Что делает new

Экземпляр создаёт оператор new. Разберём по шагам запись new User("Ann", 30):

  1. new создаёт новый пустой объект.
  2. Затем вызывает метод constructor с аргументами "Ann" и 30.
  3. Внутри constructor слово this обозначает этот новый объект, поэтому this.name = name записывает в него свойство name, а this.age = age — свойство age.
  4. new возвращает готовый объект, и он попадает в константу ann.

Под капотом класс — особая функция: typeof User даёт "function". Но вызвать её можно только через new: что будет без него, показывает частая ошибка в конце урока.

Методы общие для всех

Метод isAdult один на все экземпляры: в каждый объект он не копируется. При вызове tom.isAdult() в this оказывается tom, как у любого метода, вызванного через точку. Поэтому каждый экземпляр отвечает про свой возраст.

Здесь аналогия с фабрикой перестаёт работать. Готовый стул живёт сам по себе, и чертёж ему больше не нужен. Экземпляр же продолжает пользоваться методами класса: они лежат в одном месте, и все экземпляры обращаются к ним.

Поля

Свойство можно объявить прямо в теле класса, вне constructor: count = 0;. Такое свойство называют полем. Каждый экземпляр получает своё поле с начальным значением, ещё до того как выполнится тело constructor. Если других свойств нет, constructor можно не писать вовсе.

JavaScript
class Counter {
    count = 0;

    increment() {
        this.count++;
        return this.count;
    }
}

const a = new Counter();
const b = new Counter();
a.increment();
console.log(a.increment(), b.count); // 2 0

Давайте посмотрим, что происходит со счётчиками:

  1. Оба вызова new Counter() создают объекты со своим полем count, равным 0.
  2. Первый вызов a.increment() увеличивает a.count до 1.
  3. Второй вызов, внутри console.log, увеличивает его до 2 и возвращает 2.
  4. b.count по-прежнему 0: метод меняет поле того объекта, у которого его вызвали.

Строгий режим в классе

Тело класса всегда выполняется в строгом режиме, даже без строки "use strict". Если внутри метода присвоить значение переменной с опечаткой в имени, программа остановится с ReferenceError, а глобальная переменная не появится. Так опечатку видно сразу, а не через час поиска.

Частая ошибка

Класс вызвали без new, как обычную функцию:

JavaScript
const bob = User("Bob", 20); // ✗
TEXT
TypeError: Class constructor User cannot be invoked without 'new'

Это сообщение Node.js и Chrome. Обычная функция выполнилась бы и без new, а класс такой вызов запрещает и сразу останавливает программу. Экземпляр создают только через new: new User("Bob", 20).

Главное

  • Класс один раз описывает объекты одного вида, а new собирает по нему экземпляры.
  • new создаёт пустой объект, вызывает constructor с this на этом объекте и возвращает объект.
  • Методы класса общие для всех экземпляров, а поля у каждого экземпляра свои.
  • Класс вызывают только через new, и его тело всегда работает в строгом режиме.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом