Геттеры и сеттеры: управление доступом к свойствам
Зачем нужны геттеры и сеттеры?
Представь, что у тебя есть объект user с полем age:
const user = {
name: "Alex",
age: 25
};
Что произойдёт, если кто-то установит отрицательный возраст? 🤔
user.age = -100; // Ой-ой, так не годится!
Геттеры и сеттеры — это "сторожа" для свойств объекта. Они позволяют контролировать:
- Чтение свойства (геттер)
- Запись свойства (сеттер)
Базовый синтаксис
Вот как выглядит простейший геттер и сеттер:
const user = {
_age: 25, // Подчеркём — это "приватное" поле
get age() {
return this._age;
},
set age(value) {
if (value < 0) {
console.log("Возраст не может быть отрицательным!");
return;
}
this._age = value;
}
};
Теперь попробуем:
user.age = -30; // "Возраст не может быть отрицательным!"
console.log(user.age); // 25 (значение не изменилось)
💡 Обрати внимание: мы используем
_ageкак внутреннее поле, а публичный интерфейс — простоage.
Умные свойства
Геттеры и сеттеры делают свойства "умными". Вот несколько крутых применений:
1. Автоматическое форматирование
const product = {
price: 100,
get formattedPrice() {
return `$${this.price}`;
}
};
console.log(product.formattedPrice); // "$100"
2. Валидация данных
const person = {
_birthYear: 1990,
get age() {
return new Date().getFullYear() - this._birthYear;
},
set birthYear(value) {
if (value > new Date().getFullYear()) {
throw new Error("Год рождения не может быть в будущем!");
}
this._birthYear = value;
}
};
3. Вычисляемые свойства
const rectangle = {
width: 10,
height: 5,
get area() {
return this.width * this.height;
}
};
console.log(rectangle.area); // 50
Геттеры без сеттеров
Иногда нужно сделать свойство "только для чтения":
const constants = {
get PI() {
return 3.14159;
}
};
console.log(constants.PI); // 3.14159
constants.PI = 3; // Ничего не произойдёт (в strict mode будет ошибка)
Совместимость с existing-кодом
Геттеры/сеттеры полностью прозрачны для внешнего кода:
class User {
constructor(name) {
this.name = name;
this._accessCount = 0;
}
get accessCount() {
return ++this._accessCount;
}
}
const admin = new User("Danila");
console.log(admin.accessCount); // 1
console.log(admin.accessCount); // 2
🔥 Кстати, в классах синтаксис геттеров/сеттеров особенно элегантен!
Когда стоит использовать?
| Ситуация | Подходит? |
|---|---|
| Нужна валидация | ✅ Идеально |
| Вычисляемые значения | ✅ Отлично |
| Логирование доступа | ✅ Хорошо |
| Простые публичные поля | ❌ Избыточно |
Подводные камни
1. Рекурсия: Не называй геттер так же, как внутреннее свойство!
// ❌ Ошибка: бесконечная рекурсия!
const oops = {
get value() {
return this.value; // Вызывает самого себя!
}
};
2. Производительность: Геттеры/сеттеры медленнее прямого доступа к полям (но в 99% случаев это неважно).
Практическое задание
Создай объект temperature с:
- Приватным полем
_celsius - Геттером/сеттером
celsius - Геттером
fahrenheit, который преобразует температуру
Решение:
const temperature = {
_celsius: 0,
get celsius() {
return this._celsius;
},
set celsius(value) {
if (value < -273.15) {
throw new Error("Температура ниже абсолютного нуля!");
}
this._celsius = value;
},
get fahrenheit() {
return this._celsius * 9/5 + 32;
}
};
Проверка:
temperature.celsius = 25;
console.log(temperature.fahrenheit); // 77
Финал
Геттеры и сеттеры — мощный инструмент для:
- Контроля доступа к данным
- Валидации значений
- Создания "умных" свойств
Используй их там, где нужно добавить логику вокруг обычных свойств объекта! 🔥