$ sudo teach IT
РАЗДЕЛ 8 · УРОК 2

Геттеры и сеттеры

Представьте свойство объекта, которое выглядит как обычное поле — но при чтении вычисляется, а при записи проверяет значение. Это геттеры и сеттеры — мощный инструмент для создания «умных» свойств с валидацией и вычислениями на лету.

⏱ ~20 минут 🎓 Для новичков ⚡ JavaScript

🤔 Зачем нужны геттеры?

Допустим, у нас есть объект пользователя с именем и фамилией:

const user = {
  firstName: "Иван",
  lastName: "Петров"
};

Часто нам нужно полное имя — "Иван Петров". Можно написать метод:

const user = {
  firstName: "Иван",
  lastName: "Петров",
  getFullName() {
    return this.firstName + " " + this.lastName;
  }
};

console.log(user.getFullName()); // Иван Петров

Работает! Но есть маленькая неудобность — нужно вызывать метод со скобками: user.getFullName(). Это нарушает интуицию: мы же хотим читать свойство, а не вызывать функцию.

Геттер решает именно эту проблему: он выглядит как обычное свойство, но внутри — функция.

🎯 Геттер (get) — это метод, который вызывается автоматически, когда вы читаете свойство. Снаружи выглядит как поле, внутри — функция.

✍️ Синтаксис геттера: ключевое слово get

Перепишем пример выше с геттером:

const user = {
  firstName: "Иван",
  lastName: "Петров",

  get fullName() {                           // геттер — ключевое слово get
    return this.firstName + " " + this.lastName;
  }
};

// Обращаемся как к обычному свойству — БЕЗ скобок!
console.log(user.fullName); // Иван Петров

Заметьте разницу: теперь мы пишем user.fullName без скобок — как будто это обычное поле. Но на самом деле JavaScript видит слово get и знает: при обращении к этому свойству нужно вызвать функцию и вернуть её результат.

Метод (нужны скобки)
user.getFullName()
// Иван Петров
Геттер (без скобок)
user.fullName
// Иван Петров

Геттер — это «умное» свойство, только для чтения. Попробуйте присвоить ему значение без сеттера — и ничего не произойдёт (в строгом режиме будет ошибка).

🔒 Сеттер: перехватываем присваивание

Сеттер — это противоположность геттера. Он вызывается, когда вы присваиваете значение свойству.

🎯 Сеттер (set) — это метод, который вызывается автоматически, когда вы присваиваете значение свойству. Позволяет валидировать данные или делать побочные действия при изменении.

Классический пример — объект пользователя, где полное имя можно и читать, и задать одной строкой:

const user = {
  firstName: "Иван",
  lastName: "Петров",

  get fullName() {
    return this.firstName + " " + this.lastName;
  },

  set fullName(value) {                      // сеттер — ключевое слово set
    const parts = value.split(" ");          // разбиваем строку по пробелу
    this.firstName = parts[0];               // первое слово → имя
    this.lastName = parts[1] || "";          // второе слово → фамилия
  }
};

console.log(user.fullName); // Иван Петров

user.fullName = "Мария Сидорова"; // вызывается сеттер
console.log(user.firstName); // Мария
console.log(user.lastName);  // Сидорова
console.log(user.fullName);  // Мария Сидорова

Разберём строку set fullName(value): сеттер всегда принимает ровно один аргумент — новое значение, которое пытаются присвоить. Внутри мы решаем, что с этим значением делать: разбиваем строку, валидируем, обновляем другие свойства.

🛡️ Главная сила сеттеров — валидация

Самое полезное применение сеттеров — это проверка данных перед сохранением. Без сеттера ничто не мешает задать отрицательный возраст или пустое имя. С сеттером — мы контролируем каждое присваивание:

const person = {
  _age: 0,               // нижнее подчёркивание — условное соглашение
                         // "это внутреннее поле, не трогай напрямую"
  get age() {
    return this._age;
  },

  set age(value) {
    if (typeof value !== "number") {
      console.log("Возраст должен быть числом!");
      return;
    }
    if (value < 0 || value > 150) {
      console.log("Некорректный возраст: " + value);
      return;
    }
    this._age = value; // всё проверено — сохраняем
  }
};

person.age = 25;    // OK
console.log(person.age); // 25

person.age = -5;    // Некорректный возраст: -5
console.log(person.age); // 25 (не изменился)

person.age = "много"; // Возраст должен быть числом!
console.log(person.age); // 25 (не изменился)

Обратите внимание на _age (с нижним подчёркиванием). Это негласное соглашение в JavaScript: подчёркивание означает «внутреннее поле, не рекомендуется использовать снаружи». Снаружи работаем через person.age (геттер/сеттер), внутри храним в _age.

⚠️ Нельзя называть геттер и внутреннее поле одинаково: get age() и age: 0 одновременно — это вызовет бесконечную рекурсию. Поэтому используется _age для хранения и age для доступа.

⚙️ Вычисляемые свойства: геттер для возраста

Другое отличное применение геттеров — вычисляемые свойства, которые автоматически обновляются. Вместо того чтобы хранить возраст (который нужно каждый год обновлять), можно хранить дату рождения и вычислять возраст на лету:

const person = {
  name: "Анна",
  birthYear: 1998,

  get age() {
    const currentYear = new Date().getFullYear();
    return currentYear - this.birthYear;
  }
};

console.log(person.name); // Анна
console.log(person.age);  // 27 (вычисляется автоматически!)

Каждый раз при обращении к person.age геттер вызывает new Date().getFullYear() и вычисляет актуальный возраст. Не нужно обновлять поле каждый год — данные всегда свежие.

Хранить возраст

❌ Нужно обновлять каждый год. Можно забыть. Устаревает.

Хранить год рождения + геттер

✅ Всегда актуально. Вычисляется в момент обращения.

🏫 Геттеры и сеттеры в классе

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

class User {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

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

  set fullName(value) {
    [this.firstName, this.lastName] = value.split(" ");
  }
}

const u = new User("Пётр", "Иванов");
console.log(u.fullName);       // Пётр Иванов
u.fullName = "Сергей Смирнов";
console.log(u.firstName);      // Сергей

Синтаксис идентичен — get и set перед именем метода. Разница только в том, что это внутри class {...}.

🎯 Когда использовать геттеры и сеттеры

✅ Используй геттер, когда:

  • Свойство вычисляется из других свойств (fullName из firstName + lastName)
  • Значение должно быть всегда актуальным (возраст из даты рождения)
  • Хочешь, чтобы свойство выглядело как поле, но вело себя как функция

✅ Используй сеттер, когда:

  • Нужна валидация при установке значения (проверить тип, диапазон, формат)
  • Присваивание одного свойства должно обновить несколько других
  • Нужно сделать побочные действия при изменении (логирование, уведомления)

❌ Не используй, когда:

  • Свойство простое — просто храни значение в обычном поле
  • Вычисление очень тяжёлое — лучше кешировать результат в методе
  • Логика слишком сложная — выноси в обычные методы с говорящими именами

✅ Итоги урока

  • Геттер (get) — метод, вызываемый при чтении свойства. Выглядит как поле, работает как функция
  • Сеттер (set) — метод, вызываемый при присваивании значения. Принимает один аргумент — новое значение
  • Синтаксис: get propName() {} и set propName(value) {} — в объектном литерале или в классе
  • Геттеры отлично подходят для вычисляемых свойств: fullName, age, total
  • Сеттеры — для валидации: проверяй данные перед сохранением, отклоняй некорректные
  • Внутреннее поле хранят с _: _age, снаружи доступ через геттер/сеттер age
  • В классах синтаксис геттеров и сеттеров идентичен — те же слова get и set

В следующем уроке — классы: синтаксис class, конструктор, методы, статические поля и приватные свойства. 🚀

Геттеры и сеттеры

6 вопросов

Геттер fullName

// Создайте объект user с полями firstName и lastName. // Добавьте геттер fullName, который возвращает "firstName lastName". // Добавьте сеттер fullName, который разбивает строку по пробелу // и устанавливает firstName и lastName. const user = { firstName: 'Иван', lastName: 'Петров', // ваш код здесь };

Валидация возраста через сеттер

// Создайте объект person с внутренним полем _age. // Геттер age возвращает _age. // Сеттер age проверяет: если значение не число или // меньше 0 или больше 150 — не сохраняет его. const person = { _age: 0, // ваш код здесь };