Геттеры и сеттеры
Иногда свойство должно не просто хранить значение, а что-то делать: вычислять результат на лету или проверять, что в него записывают. Для этого есть геттеры и сеттеры — методы, которые снаружи выглядят как обычные свойства.
Геттер
Слово get перед методом превращает его в геттер. К нему обращаются как к свойству, без скобок, а возвращает он результат метода:
class User {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
const user = new User('Анна', 'Смирнова');
console.log(user.fullName); // Анна СмирноваВычисляемое значение всегда актуально
Геттер вычисляет значение при каждом обращении, поэтому оно не устаревает, когда меняются исходные данные:
class Cart {
items = [];
get total() {
return this.items.reduce((sum, item) => sum + item.price, 0);
}
}
const cart = new Cart();
cart.items.push({ title: 'Чай', price: 5 });
cart.items.push({ title: 'Кофе', price: 12 });
console.log(cart.total); // 17Хранить сумму в отдельном свойстве и не забывать её пересчитывать не нужно.
Сеттер
Слово set объявляет сеттер — метод, который вызывается при записи в свойство. Записанное значение приходит в его параметр:
class User {
set name(value) {
this.firstName = value.trim();
}
}
const user = new User();
user.name = ' Олег ';
console.log(user.firstName); // ОлегПроверка значения
Главная польза сеттера — проверка данных. Вместе с приватным полем он не даст записать в объект неверное значение:
class Product {
#price = 0;
get price() {
return this.#price;
}
set price(value) {
if (value < 0) {
throw new Error('Цена не может быть отрицательной');
}
this.#price = value;
}
}
const product = new Product();
product.price = 25;
console.log(product.price); // 25Запись product.price = -5 выбросила бы ошибку, и неверная цена не попала бы в объект.
Свойство только для чтения
Если объявить геттер без сеттера, свойство можно только читать. Запись в него не срабатывает: в обычном скрипте она молча пропускается, а в модулях и строгом режиме вызывает ошибку TypeError:
class Circle {
constructor(radius) {
this.radius = radius;
}
get diameter() {
return this.radius * 2;
}
}
const circle = new Circle(5);
circle.diameter = 100;
console.log(circle.diameter); // 10Частая ошибка
Внутри сеттера нельзя записывать значение в свойство с тем же именем. Такая запись снова вызывает сеттер, тот — снова себя, и программа падает с ошибкой переполнения стека:
class User {
set name(value) {
this.name = value; // сеттер вызывает сам себя бесконечно
}
}Значение храните в поле с другим именем — обычно в приватном: this.#name = value.