Декораторы — это действительно полезная функция, которая позволяет нам расширять классы JavaScript. Самый популярный случай использования декораторов — это когда мы хотим сохранить единственную ответственность (SOLID). В этой статье я собираюсь шаг за шагом показать вам, как настроить среду и использовать функцию JavaScript уже сегодня!

Конфигурация

Первое, что нам нужно, это установить несколько пакетов, которые помогут нам настроить babel и webpack, мы должны сделать это, потому что мы используем современный JavaScript, который еще не вошел в стандарт еще.

Список пакетов:

Я также приложил пару скриптов, которые запускают сборщик веб-пакетов.

Как вы заметили, помимо пакетов по умолчанию я установил несколько дополнительных в качестве пакетов зависимостей для разработчиков, а именно:

@babel/plugin-proposal-decorators
@babel/plugin-proposal-class-properties

Первый плагин включает функцию декоратора, а второй позволяет нам использовать свойства внутри класса, не беспокоясь о совместимости со старыми браузерами. Пришло время настроить bable:

И настроим веббэк, определим правила преобразования нашего кода в совместимый код для всех браузеров, нам нужно описать порядок загрузчиков, входной и выходной файл. Я также добавляю следующие плагины:

HtmlWebpackPlugin()
CleanWebpackPlugin()

Плагин HtmlWebpackPlugin() создает HTML-страницу, на которой будет выполняться наш код JavaScript, а CleanWebpackPlugin() — это просто служебный плагин, очищающий нашу папку dist после каждого сборка сборки. Полная конфигурация webpack:

Декоратор метода

Время кодировать, я подготовил простой пример, который иллюстрирует все преимущества использования декоратора:

У нас есть очень простая функция sum(a, b), в ее обязанности входит только суммирование двух значений, но мы хотим регистрировать каждую часть вычисления, а не модифицировать текущую реализацию.

Как видите, декоратор имеет особый синтаксис, начинающийся с символа @. Функция logging(target) — это просто прокси, мы могли бы поймать обернутую функцию декоратора, например:

const originalFn = target.descriptor.value

Итак, следующим шагом является переписывание текущего значения дескриптора, которое будет принимать некоторые аргументы, необходимые для получения возможности передавать числа для суммирования, которые будут применяться к исходной функции.

В промежутках вычислений мы добавляем дополнительные функции регистрации, не изменяя исходную логику sum(a, b).

Свойство дескриптора в деталях

Между прочим, свойство дескриптора обладает большей силой, чем вы думаете. Мы можем управлять доступностью объекта, используя следующие свойства:

target.descriptor.value
target.descriptor.writable
target.descriptor.enumerable
target.descriptor.configurable
  • target.descriptor.value — значение свойства (вы видели это, когда мы получили оригинальную функцию);
  • target.descriptor.writable — свойство может быть изменено;
  • target.descriptor.enumerable — свойство проявляется во время перечисления, например, в циклах;
  • target.descriptor.configurable — дескриптор свойства может быть изменен, а свойство может быть удалено из текущего объекта.

Краткое содержание

Мы рассмотрели главное преимущество использования декоратора, он действительно помогает нам, когда мы хотим расширить объект с помощью дополнительной логики, а не изменять его исходное поведение, и дает нашим классам одну причину для изменения.

Полный код вы можете увидеть здесь.

Рекомендации

  1. https://github.com/tc39/предложение-декораторы
  2. https://en.wikipedia.org/wiki/Single-responsibility_principle
  3. https://babeljs.io/docs/en/babel-plugin-proposal-class-properties
  4. https://babeljs.io/docs/en/babel-plugin-proposal-decorators
  5. https://webpack.js.org/loaders/babel-loader