подробное руководство, когда и как использовать мемоизацию в JavaScript: лучшие практики и примеры.
Каждый из нас был разочарован приложением, которое просто слишком долго загружается. Низкая производительность может сильно раздражать, будь то веб-сайт, который слишком долго отображается, приложение, которое открывается вечно, или функция в приложении, выполнение которой занимает слишком много времени. Это не только раздражает клиентов, но также может стоить бизнесу денег и нанести ущерб репутации компании.
Один из способов решить проблему медленных приложений – использовать запоминание – технику, которая помогает оптимизировать и ускорить выполнение функций.
Что такое мемоизация?
В JavaScript мемоизация – это эффективный метод повышения производительности функций. Включает кэширование результатов дорогостоящих вызовов функций, чтобы к ним можно было быстро получить доступ, а не пересчитывать их каждый раз при вызове функции. Используя запоминание, вы можете значительно сократить количество времени и ресурсов, потребляемых вашим кодом, и создавать более эффективные и масштабируемые приложения.
Для иллюстрации предположим, что у вас есть функция, которая требует времени для вычисления факториала числа. Если вы используете запоминание, функция сохранит вычисленный результат и будет использовать его каждый раз при вводе одного и того же числа. В результате функция будет выполняться значительно быстрее, если вы вызовете ее снова с тем же номером, поскольку она будет извлекать сохраненный результат из кеша, а не вычислять его с нуля.
В этом посте мы подробно рассмотрим преимущества концепции мемоизации в JavaScript. Мы рассмотрим, как он работает, когда его использовать, и приведем примеры использования. К тому времени, когда вы закончите читать эту статью, у вас будет полное представление о том, как мемоизация может улучшить функциональность вашего кода.
Зачем использовать мемоизацию?
Допустим, у вас есть функция, которая вычисляет n-е число в последовательности Фибоначчи:
function fib(n) { if (n <= 1) { return n } return fib(n - 1) + fib(n - 2) } fib(9) // outputs: 34 default: 0.13916015625 ms
Эта функция отлично работает при малых значениях n и занимает 0,13 мс для выполнения, но по мере увеличения n
ее выполнение может занять много времени. Например, вычисление fib(40)
занимает несколько миллисекунд, а fib(50)
— несколько секунд.
function fib(n) { if (n <= 1) { return n } return fib(n - 1) + fib(n - 2) } console.time() fib(40) // outputs: 102334155 default: 1380.770751953125 ms console.timeEnd()
В приведенном выше примере вы можете видеть, что для выполнения fib(40)
потребовалось 1380,77 мс. Если эта функция fib(40)
запускается снова и снова с одним и тем же аргументом, ее выполнение займет несколько миллисекунд. Это может привести к проблемам с производительностью и требует оптимизации. Используя мемоизацию, мы можем сократить время вычислений и оптимизировать функцию fib()
.
Чтобы оптимизировать эту функцию с помощью мемоизации, мы можем кэшировать результаты каждого вычисления с помощью объекта:
const memoize = (func) => { const cache = {}; }
В приведенном выше примере я создал функцию с именем «memoize», которая принимает другую функцию в качестве аргумента и содержит в себе пустой объект с именем «кэш».
Продолжим с функцией memoize:
const memoize = (func) => { const cache = {}; return (...args) => { const key = args[0]; if (key in cache) { return cache[key]; } else { const result = func(key); cache[key] = result; return result; } } }
Запоминаемая функция, возвращаемая memoize
, имеет объект кеша, который используется для хранения результатов предыдущих вызовов func
. Объект кеша изначально является пустым объектом.
В этой реализации memoize
используется функция стрелки и синтаксис остальных параметров (...args
) для захвата произвольного количества аргументов, передаваемых функции запоминания.
Затем он использует поиск свойств объекта, чтобы проверить, существует ли [ключ] в объекте кеша, и оператор in
, чтобы определить, присутствует ли [ключ] в объекте. Если [ключ] существует в объекте кеша, возвращается кэшированный результат.
В противном случае функция ввода вызывается с аргументами, а результат сохраняется в объекте кеша (cache[key] = result;) с использованием первого аргумента в качестве [ключа].
Вот полный код -
function fib(n) { if (n <= 1) { return n } return fib(n - 1) + fib(n - 2) } const memoize = (func) => { const cache = {}; return (...args) => { const key = args[0]; if (key in cache) { return cache[key]; } else { const result = func(key); cache[key] = result; return result; } } } const result = memoize(fib) console.time() console.log(result(40)); //Output 832040 "default: 1390.040771484375 ms" console.timeEnd() console.time() console.log(result(40)); //Output 832040 "default: 0.041015625 ms" console.timeEnd()
И теперь, когда вы запускаете memoize
с аргументом fib(40)
несколько раз, вы можете видеть, что мемоизированная версия функции работает значительно быстрее исходной функции: для вычисления fib(40)
требуется всего 0,04 мс вместо 1390,04. мс.
Это всего лишь один пример того, как мемоизацию можно использовать для оптимизации выполнения функций в JavaScript. Кэшируя результаты дорогостоящих вызовов функций, вы можете значительно повысить производительность своего кода и создавать более эффективные и масштабируемые приложения.
Когда использовать мемоизацию?
Мемоизацию можно использовать в ситуациях, когда у вас есть функция, которая часто вызывается с одними и теми же входными параметрами и требует много времени для вычисления. Кэшируя результаты предыдущих вызовов функций, вы можете избежать повторного вычисления одного и того же результата несколько раз.
Вот несколько распространенных сценариев, в которых мемоизация может быть полезна:
- Рекурсивные функции. Рекурсивные функции часто выигрывают от запоминания, поскольку они часто вызывают себя повторно с одними и теми же входными параметрами.
- Дорогие вычисления. Если ваша функция выполняет ресурсоемкую операцию, например сортировку большого массива или выполнение вызова API, можно использовать мемоизацию, чтобы избежать повторения операции для одних и тех же входных параметров.
- Неизменяемые данные. Если ваша функция работает с неизменяемыми данными, можно использовать запоминание, чтобы избежать повторного вычисления результата функции для одних и тех же входных параметров, поскольку результат всегда будет одним и тем же.
- Извлечение данных. Если ваша функция извлекает данные из базы данных или внешнего источника, можно использовать мемоизацию, чтобы избежать многократного выполнения одного и того же запроса для одних и тех же входных параметров.
В заключение,запоминание — это ценный инструмент, который должен быть в вашем наборе инструментов для оптимизации, и может помочь вам создавать более эффективные и масштабируемые приложения.
Важно отметить, что мемоизацию следует использовать с осторожностью, поскольку она может привести к утечке памяти, если она не реализована правильно. Обязательно используйте соответствующие стратегии кэширования и ограничьте размер кэша, чтобы не хранить слишком много данных в памяти.
Спасибо за прочтение ! Надеюсь, вам понравилось узнавать об этой фантастической технике оптимизации.
Если она вам понравилась, поделитесь ею с друзьями, я буду очень признателен🧡.
Изучите продвинутую концепцию javascript.
Спасибо 🙂