Паттерн отложенной загрузки в JavaScript

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

Традиционно разработчики создают свойства внутри классов JavaScript для любых данных, которые могут потребоваться в экземпляре. Это не проблема для небольших фрагментов данных, которые легко доступны внутри конструктора. Однако, если некоторые данные необходимо рассчитать, вы можете не захотеть рассчитывать их до того времени как в них возникнет необходимость. Например, рассмотрим этот класс:

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

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

Паттерн использования по требованию

Самый простой способ оптимизировать выполнение дорогостоящей операции — дождаться, пока данные потребуются, прежде чем выполнять вычисления. Например, вы можете использовать свойство доступа с геттером для выполнения вычислений по запросу:

В этом случае ваши дорогостоящие вычисления не будут выполняться до тех пор, пока кто-то не прочитает свойство data в первый раз, что является улучшением. Однако такие же дорогостоящие вычисления выполняются каждый раз при чтении свойства data, что хуже, чем в предыдущем примере, где, по крайней мере, вычисление выполнялось только один раз. Это не очень хорошее решение.

Паттерн беспорядочной ленивой загрузки

Вычисление при доступе к свойству — хорошее начало. Что вам действительно нужно, так это кэшировать информацию после этого момента и просто использовать кешированную версию. Но где вы храните эту информацию для облегчения доступа? Самый простой подход — определить свойство с тем же именем и установить его значение для вычисленных данных, например:

Здесь свойство data снова определяется как геттер класса, но на этот раз оно кэширует результат. Вызов Object.defineProperty() создает новое свойство data с фиксированным значением actualData. После этого возвращается само значение. В следующий раз, когда к свойству data обращаются, оно будет читать из вновь созданного свойства, а не вызывать геттер:

Фактически, все вычисления выполняются только при первом чтении свойства data. Каждое последующее чтение свойства data возвращает кешированную версию.

Единственным недостатком этого шаблона является то, что свойство data начинается как неперечисляемое свойство-прототип и заканчивается как неперечисляемое собственное свойство:

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

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

Паттерн отложенной загрузки

Если у вас есть вариант использования, когда важно, чтобы свойство с ленивой загрузкой всегда существовало в экземпляре, вы можете использовать Object.defineProperty() для создания свойства внутри конструктора класса. Это немного сложнее, чем в предыдущем примере, но это гарантирует, что свойство существует только в экземпляре. Вот пример:

Здесь конструктор создает свойство data, используя Object.defineProperty(). Свойство создается в экземпляре (с помощью this), а также указывает свойство, которое должно быть перечислимым и настраиваемым (типично для собственных свойств). Особенно важно установить свойство data как настраиваемое, чтобы его можно было снова вызвать Object.defineProperty().

Затем выполняется вычисление и вызывается Object.defineProperty() второй раз. Вычисленные данные возвращаются из геттера. В следующий раз, когда свойство data будет прочитано, оно будет прочитано из сохраненного значения. В качестве бонуса свойство data теперь существует только как собственное свойство и действует одинаково как до, так и после первого чтения:

Для классов это, скорее всего, шаблон, который вы хотите использовать; литералы объектов, с другой стороны, могут использовать более простой подход.

Паттерн отложенной загрузки для литералов

Если вы используете объектный литерал вместо класса, процесс должен быть проще, потому что геттеры, определенные в объектных литералах, определяются как перечислимые собственные свойства (а не свойства прототипа), так и свойства данных. Это означает, что вы можете использовать беспорядочный паттерн ленивой загрузки для классов:

Заключение

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

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

Автор: Nicholas C. Zakas

Источник: humanwhocodes.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

JavaScript. Полное руководство

Изучите самый популярный язык разработки и станьте высокооплачиваемым профи

Подробнее

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Комментирование закрыто.