Decorators: декораторы классов и методов (экспериментальный)
Что такое декораторы и зачем они нужны? 🛠️
Декораторы в JavaScript — это специальные функции, которые модифицируют поведение классов, методов или свойств. Они позволяют добавлять новую функциональность, не меняя исходный код.
💡 Декораторы — это пока экспериментальная возможность (Stage 3). Для работы включите флаг
--experimental-decoratorsили настройте Babel.
Как выглядят декораторы? ✨
Синтаксис декораторов прост — это функция с префиксом @. Например:
@logTime
class Calculator {
@memoize
add(a, b) {
return a + b;
}
}
Здесь:
@logTime— декоратор класса, логирующий время создания экземпляра.@memoize— декоратор метода, кэширующий результаты вызовов.
Виды декораторов 🏷️
1. Декораторы класса
Принимают конструктор класса и могут его модифицировать или заменить.
Пример: Добавляем свойство version всем экземплярам.
function addVersion(constructor) {
constructor.prototype.version = '1.0.0';
}
@addVersion
class Car {}
const myCar = new Car();
console.log(myCar.version); // '1.0.0'
2. Декораторы методов
Принимают три параметра: целевой объект, имя метода и дескриптор свойства.
Пример: Логируем вызовы метода.
function log(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`Called: ${name}(${args})`);
return original.apply(this, args);
};
return descriptor;
}
class Math {
@log
square(n) {
return n * n;
}
}
const m = new Math();
m.square(4); // Выведет: "Called: square(4)"
3. Декораторы свойств
Работают аналогично методам, но для свойств класса.
Пример: Делаем свойство только для чтения.
function readonly(target, key, descriptor) {
descriptor.writable = false;
return descriptor;
}
class User {
@readonly
role = 'admin';
}
const u = new User();
u.role = 'user'; // Ошибка! Свойство только для чтения.
Комбинирование декораторов 🔄
Декораторы можно накладывать несколько раз — они применяются сверху вниз:
@decorator1
@decorator2
class Example {}
Порядок выполнения: decorator2 → decorator1.
Реальный пример: Кэширование методов 🗃️
Декоратор @memoize сохраняет результаты вызовов, избегая повторных вычислений:
function memoize(target, name, descriptor) {
const cache = new Map();
const original = descriptor.value;
descriptor.value = function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = original.apply(this, args);
cache.set(key, result);
return result;
};
return descriptor;
}
class Fibonacci {
@memoize
calc(n) {
return n <= 1 ? n : this.calc(n - 1) + this.calc(n - 2);
}
}
const fib = new Fibonacci();
console.log(fib.calc(100)); // Быстро, благодаря кэшу!
Ограничения и подводные камни ⚠️
- Нельзя декорировать функции (только классы, методы и свойства).
- Не поддерживается в стандарте ES2023 (пока Stage 3).
- Проблемы с
this— контекст может теряться, если не аккуратно писать декораторы.
🔥 Совет: Для продакшена используйте Babel с плагином
@babel/plugin-proposal-decorators.
Где это применяется на практике? 🌍
- Валидация данных — проверка аргументов методов.
- Авторизация — ограничение доступа к методам.
- Логирование — трассировка вызовов.
- Оптимизация — кэширование и мемоизация.
Итоги 🏁
Декораторы — мощный инструмент для:
- ✅ Улучшения читаемости кода.
- ✅ Повторного использования логики.
- ✅ Модификации поведения без изменения исходников.
Экспериментируйте, но помните — это пока не стандарт!
// Ваш код после этого урока:
@supercharge
class MyProject {
@debug
awesomeMethod() {
// Магия декораторов ✨
}
}