Приватные поля и static
В уроке о геттерах свойство minutes показывало данные объекта по правилу. Но сами данные, свойство seconds, мог переписать любой код снаружи класса. Иногда так нельзя.
Представьте сейф с окошком. Деньги лежат внутри, и рукой до них не дотянуться. Посмотреть сумму или положить купюру можно только через окошко, а как оно работает, решил тот, кто делал сейф.
В классе сейф — это приватное поле, а окошко — методы и геттеры самого класса. Вот класс Money: он хранит сумму в центах и не даёт менять её снаружи.
class Money {
#cents;
constructor(cents) {
this.#cents = cents;
}
get dollars() {
return this.#cents / 100;
}
static fromDollars(dollars) {
return new Money(dollars * 100);
}
}
const m = Money.fromDollars(3);
console.log(m.dollars, m.fromDollars); // 3 undefinedПриватные поля
Приватное поле — это поле, имя которого начинается с #. Его объявляют в теле класса, как #cents; выше, а методы читают и меняют его через this.#cents.
Решётка — часть имени: #cents и cents — два разных поля. Синтаксическая ошибка, после которой программа не запустится, возникает в двух случаях:
- класс обращается к
this.#cents, а поле#cents;в его теле не объявлено, даже если обращение стоит вconstructor; - код вне класса пишет
m.#cents: снаружи поле не видно.
Так класс защищает свои данные: изменить их можно только через его методы. Здесь сравнение с сейфом кончается. Сейф можно взломать, а у кода снаружи класса нет способа прочитать приватное поле.
Геттер без сеттера
Прочитать сумму снаружи можно только через геттер dollars. Изменить её нельзя: сеттера у класса нет, а поле #cents снаружи не видно.
Свойству, у которого есть только геттер, нельзя присвоить значение и внутри класса: this.dollars = 5 в методе остановит программу с TypeError. Поэтому сами данные хранят под другим именем, как #cents, а геттер только показывает их.
На собеседовании спрашивают, как в JavaScript спрятать данные объекта. Ответ: приватным полем с # или замыканием.
Статические методы
В классе Money есть ещё один особый метод — fromDollars. Статический метод — это метод со словом static. Он принадлежит самому классу, как Array.isArray: его вызывают как Money.fromDollars(3), а у экземпляра m его нет.
Вернёмся на мебельную фабрику. Обычный метод — умение готового стула. Статический — окно заказов самой фабрики: заказ принимает фабрика и выдаёт новый стул.
Чаще всего статический метод так и работает: создаёт объект иначе, чем constructor. Конструктор Money ждёт центы, а fromDollars принимает доллары и сам переводит их в центы.
Разберём последние строки примера:
Money.fromDollars(3)вызывается через класс и возвращаетnew Money(300).m.dollarsзапускает геттер и даёт3:300 / 100.m.fromDollarsдаётundefined: у экземпляра статического метода нет, и ошибки при чтении не возникает.
Частая ошибка
Статический метод вызвали через экземпляр:
const price = m.fromDollars(5); // ✗TypeError: m.fromDollars is not a functionЧтение m.fromDollars даёт undefined, и скобки пытаются вызвать undefined как функцию. Статический метод вызывают через класс: Money.fromDollars(5).
Главное
- Приватное поле
#объявляют в теле класса, и снаружи его не видно. - Свойству только с геттером нельзя присвоить значение, даже внутри класса.
- Статический метод вызывают через класс, а у экземпляров его нет.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.