Геттеры и сеттеры в объектах

Геттеры и сеттеры в объектах

Технический фундамент get/set

Геттер и сеттер — это дескрипторы свойства: они перехватывают чтение и запись поля через единый интерфейс.

const state = {
  _value: 1,
  get value() {
    return this._value;
  },
  set value(v) {
    this._value = Number(v);
  },
};

state.value = '42';
console.log(state.value); // 42

Ключевой момент: снаружи это выглядит как обычное поле, но внутри выполняется логика.

Базовый пример

const user = {
  firstName: 'Ann',
  lastName: 'Lee',

  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  },

  set fullName(value) {
    const [first, last] = value.split(' ');
    this.firstName = first;
    this.lastName = last;
  },
};

console.log(user.fullName); // Ann Lee
user.fullName = 'Max Fox';
console.log(user.firstName); // Max

Смотри, что важно: вызываются без () как обычное свойство.

Зачем это полезно

  • валидация входа в set;
  • вычисляемое поле в get;
  • скрытие внутренней структуры объекта.
const product = {
  _price: 0,

  get price() {
    return this._price;
  },

  set price(value) {
    if (value < 0) return;
    this._price = value;
  },
};

Проверь себя: почему поле _price часто называют с подчеркиванием?

Подсказка: это соглашение «внутреннее поле, не трогай напрямую». Это не настоящая приватность, просто договоренность в коде.

Edge cases

Если в сеттере случайно присвоить то же свойство (this.price = value), получишь бесконечную рекурсию.

// Плохо: set price(v) { this.price = v; }
// Хорошо: set price(v) { this._price = v; }

Микро-сценарии

  1. Нормализация email при присвоении (trim, toLowerCase).
  2. Вычисление fullName из имени и фамилии без ручной склейки везде по коду.

Типичные ошибки

  • Вызывать геттер как функцию user.fullName().
  • Не отделять внутреннее хранилище (_value) от интерфейсного свойства.
  • Делать тяжелые вычисления в геттере без необходимости.
  • Использовать сеттер без валидации входа.

Краткий итог

  • get и set дают контролируемый доступ к свойствам.
  • Используются как обычные поля, без скобок вызова.
  • Геттер удобен для вычисляемых значений.
  • Сеттер удобен для валидации и нормализации.
  • Важно избегать рекурсии и разделять внешнее/внутреннее поле.