Геттеры и сеттеры
Геттеры и сеттеры
Технический фундамент контролируемого доступа
Геттеры и сеттеры решают задачу инкапсуляции на уровне свойств:
- чтение и запись выглядят как доступ к полю;
- под капотом можно валидировать, нормализовать и вычислять значения;
- интерфейс объекта остается стабильным даже при смене внутренней структуры;
- важно избегать тяжелых side effects внутри getter.
Это делает модель устойчивой к ошибкам ввода и упрощает эволюцию API класса.
Зачем геттеры и сеттеры нужны на практике
Иногда прямой доступ к свойствам класса слишком опасен: можно записать невалидное значение, сломать бизнес-логику или нарушить формат данных. Геттеры и сеттеры позволяют контролировать чтение и запись, не ломая удобный синтаксис доступа как к обычному полю.
Ключевой момент: get и set выглядят как свойства, но под капотом это методы с дополнительной логикой.
Проверь себя: почему полезно иметь проверку при записи email, даже если поле публично?
Базовый синтаксис
class User {
constructor(name) {
this._name = name;
}
get name() {
return this._name;
}
set name(value) {
if (typeof value !== 'string' || value.trim() === '') {
throw new Error('Имя должно быть непустой строкой');
}
this._name = value;
}
}
const user = new User('Анна');
console.log(user.name); // вызов getter
user.name = 'Ира'; // вызов setter
Смотри, что важно: снаружи это выглядит как обычное свойство, но ты получаешь контроль над логикой.
Смотри, что важно: setter не обязателен. Если у свойства есть только get, то оно становится read-only (в классах включен strict mode, поэтому присваивание без setter обычно приводит к ошибке).
class UserId {
constructor(id) {
this._id = id;
}
get id() {
return this._id;
}
}
const u = new UserId(1);
// u.id = 2; // TypeError: property has only a getter
Почему часто используют _ в именах
_name это соглашение, что поле внутреннее и напрямую трогать его не стоит. Это не строгая приватность, но хороший сигнал для команды.
Здесь часто путаются: если в setter написать this.name = value, получится бесконечная рекурсия. Нужно писать во внутреннее поле (this._name).
set name(value) {
this.name = value; // Ошибка: setter вызывает сам себя
}
Геттеры для вычисляемых значений
Getter можно использовать не только для возврата поля, но и для расчетов.
class Product {
constructor(price, discountPercent) {
this.price = price;
this.discountPercent = discountPercent;
}
get finalPrice() {
return this.price - (this.price * this.discountPercent) / 100;
}
}
const product = new Product(1000, 15);
console.log(product.finalPrice); // 850
Дополнительный пример: нормализация email через setter.
class Account {
constructor(email) {
this._email = '';
this.email = email;
}
get email() {
return this._email;
}
set email(value) {
if (typeof value !== 'string' || !value.includes('@')) {
throw new Error('Некорректный email');
}
this._email = value.trim().toLowerCase();
}
}
Новый термин: вычисляемое свойство - значение, которое вычисляется динамически при чтении.
Проверь себя: почему finalPrice удобнее как getter, чем как обычный метод getFinalPrice() в некоторых командах?
Микро-сценарии из продукта
- Профиль пользователя.
- setter
emailнормализует регистр и проверяет формат; - getter
displayNameвозвращает подготовленное имя для UI.
- Модель заказа.
- setter
statusразрешает только допустимые статусы; - getter
isCompletedпоказывает готовность заказа.
Такой подход сохраняет данные в консистентном состоянии.
Частые ошибки новичков
- Делать в getter тяжелые операции или сетевые вызовы.
- Писать setter без валидации там, где данные критичны.
- Использовать геттеры/сеттеры там, где обычного свойства достаточно.
- Нарушать контракт и менять типы возвращаемых значений.
Анти-провал: используй get/set там, где действительно нужна логика контроля или вычисления, а не "для красоты".
Что будет, если изменить входные данные
Если записать user.name = '', setter выбросит ошибку и защитит объект от невалидного состояния. Если записать user.name = 'Марк', значение обновится корректно. Это предсказуемая защита инвариантов модели.
Проверь себя: зачем валидировать значение в setter, если фронтенд уже проверяет форму?
Краткий итог
- Геттеры и сеттеры дают контроль над чтением и записью свойств.
- Внешне доступ остается удобным как к обычным полям.
- Setter подходит для валидации и нормализации входа.
- Getter удобен для вычисляемых свойств без лишних вызовов.
- Используй
get/setосознанно, когда это реально повышает надежность модели.