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

Приватные поля и static

В уроке о геттерах свойство minutes показывало данные объекта по правилу. Но сами данные, свойство seconds, мог переписать любой код снаружи класса. Иногда так нельзя.

Представьте сейф с окошком. Деньги лежат внутри, и рукой до них не дотянуться. Посмотреть сумму или положить купюру можно только через окошко, а как оно работает, решил тот, кто делал сейф.

В классе сейф — это приватное поле, а окошко — методы и геттеры самого класса. Вот класс Money: он хранит сумму в центах и не даёт менять её снаружи.

JavaScript
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 принимает доллары и сам переводит их в центы.

Разберём последние строки примера:

  1. Money.fromDollars(3) вызывается через класс и возвращает new Money(300).
  2. m.dollars запускает геттер и даёт 3: 300 / 100.
  3. m.fromDollars даёт undefined: у экземпляра статического метода нет, и ошибки при чтении не возникает.

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

Статический метод вызвали через экземпляр:

JavaScript
const price = m.fromDollars(5); // ✗
TEXT
TypeError: m.fromDollars is not a function

Чтение m.fromDollars даёт undefined, и скобки пытаются вызвать undefined как функцию. Статический метод вызывают через класс: Money.fromDollars(5).

Главное

  • Приватное поле # объявляют в теле класса, и снаружи его не видно.
  • Свойству только с геттером нельзя присвоить значение, даже внутри класса.
  • Статический метод вызывают через класс, а у экземпляров его нет.

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

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

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