Перейти к содержимому

28. Мемоизация

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

Мемоизация – это техника оптимизации, при которой результаты вызовов функций, принимающих определенные аргументы, кэшируются. Когда функция вызывается снова с теми же аргументами, вместо повторного вычисления возвращается сохраненный результат. Это особенно полезно для функций, которые являются ресурсоемкими (например, выполняют сложные вычисления или запросы к API) и часто вызываются с одинаковыми входными данными.

Предположим, у нас есть функция, вычисляющая n-ое число Фибоначчи:

function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(5)); // 5
console.log(fibonacci(6)); // 8

Эта функция очень неэффективна, потому что она многократно вычисляет одни и те же значения. Мемоизация может помочь это исправить:

function memoizeFibonacci() {
const cache = {}; // Создаем кэш для хранения результатов
return function fibonacci(n) {
if (n in cache) { // Проверяем, есть ли результат в кэше
return cache[n]; // Если есть, возвращаем его
}
if (n <= 1) {
return n;
}
const result = fibonacci(n - 1) + fibonacci(n - 2); // Вычисляем результат
cache[n] = result; // Сохраняем результат в кэш
return result; // Возвращаем результат
};
}
const memoFib = memoizeFibonacci();
console.log(memoFib(5)); // 5
console.log(memoFib(6)); // 8

В этом примере memoizeFibonacci возвращает функцию fibonacci, которая имеет доступ к переменной cache. При каждом вызове fibonacci сначала проверяет, есть ли результат для данного n в cache. Если есть, он возвращает сохраненный результат. В противном случае он вычисляет результат, сохраняет его в cache и возвращает.

Можно создать универсальную функцию мемоизации, которая может быть применена к любой другой функции:

function memoize(func) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args); // Преобразуем аргументы в строку для использования в качестве ключа
if (cache[key]) {
return cache[key];
}
const result = func(...args);
cache[key] = result;
return result;
};
}
function expensiveFunction(a, b) {
console.log("Выполняю сложное вычисление...");
return a + b;
}
const memoizedExpensiveFunction = memoize(expensiveFunction);
console.log(memoizedExpensiveFunction(2, 3)); // Выполняю сложное вычисление... 5
console.log(memoizedExpensiveFunction(2, 3)); // 5 (берется из кэша)
console.log(memoizedExpensiveFunction(4, 5)); // Выполняю сложное вычисление... 9

Мемоизация широко используется в различных библиотеках и фреймворках JavaScript.

  • React: Компонент React.memo использует мемоизацию для предотвращения ненужных перерисовок компонентов. Он сравнивает пропсы (props) компонента и, если они не изменились, не перерисовывает компонент, а использует ранее отрендеренный результат.
  • Redux: Функция createSelector из библиотеки reselect использует мемоизацию для оптимизации вычислений, основанных на состоянии Redux. Она пересчитывает результат только тогда, когда изменяются входные селекторы.
  • lodash: Библиотека lodash предоставляет функцию _.memoize, которая реализует мемоизацию.
  • Мемоизация – это техника оптимизации для ресурсоемких функций.
  • Результаты вызовов функций кэшируются для последующего переиспользования.
  • Мемоизация может значительно улучшить производительность, особенно при частом вызове функций с одинаковыми аргументами.
  • Важно учитывать, что мемоизация требует дополнительной памяти для хранения кэшированных результатов.
  • Универсальные функции мемоизации позволяют применять эту технику к различным функциям.
  • Мемоизация широко используется в различных JavaScript библиотеках и фреймворках.