Skip to main content

Що таке мемоізація?

1. Визначення

Мемоізація - це техніка оптимізації, при якій результати функції кешуються і при повторних викликах з тими самими аргументами беруться з пам'яті, а не обчислюються заново.

Тобто:

Якщо функція вже порахувала результат для цих вхідних даних - другого разу вона просто поверне збережене значення.


2. Приклад без мемоізації

javascript
function slowSquare(n) { console.log('Обчислюю...'); return n * n; } console.log(slowSquare(4)); // "Обчислюю..." -> 16 console.log(slowSquare(4)); // "Обчислюю..." знову -> 16

Проблема: кожен виклик заново рахує результат, навіть якщо аргумент той самий.


3. Приклад з мемоізацією

javascript
function memoizedSquare() { const cache = {}; return function (n) { if (n in cache) { console.log('Беремо з кешу'); return cache[n]; } console.log('Обчислюю...'); const result = n * n; cache[n] = result; return result; }; } const square = memoizedSquare(); console.log(square(4)); // "Обчислюю..." -> 16 console.log(square(4)); // "Беремо з кешу" -> 16

Тепер функція рахує тільки один раз, а потім віддає значення з кешу.


4. Коли мемоізація корисна

  • Функція чиста (pure) - залежить тільки від вхідних аргументів і не має побічних ефектів;
  • Функція виконує дорогі обчислення (наприклад, сортування, рекурсія, фільтрація, рендеринг);
  • Функція викликається часто з тими самими аргументами.

5. Класичні приклади

Приклад - рекурсивний fibonacci

Без мемоізації:

javascript
function fib(n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); } console.log(fib(40)); // Дуже довго!

З мемоізацією:

javascript
function memoFib() { const cache = {}; return function f(n) { if (n in cache) return cache[n]; if (n <= 1) return n; cache[n] = f(n - 1) + f(n - 2); return cache[n]; }; } const fib = memoFib(); console.log(fib(40)); // Майже миттєво

Різниця величезна: час падає з O(2ⁿ) до O(n).


6. Мемоізація в React

У React мемоізація використовується для запобігання зайвим ререндерам.

ХукЩо робитьПриклад
useMemoМемоізує результат обчисленняconst value = useMemo(() => expensiveCalc(data), [data])
useCallbackМемоізує функцію (щоб не пересоздавалася на кожен рендер)const handleClick = useCallback(() => {...}, [deps])
React.memoМемоізує компонент (не ререндерить, якщо пропси не змінилися)export default React.memo(MyComponent)

Це те саме, що й у звичайному JS, тільки на рівні React-компонентів.


7. Популярні бібліотеки

  • lodash.memoize - готова реалізація:

    javascript
    import memoize from 'lodash.memoize'; const square = memoize(x => x * x); console.log(square(5)); // обчислить console.log(square(5)); // з кешу
  • memoizee - просунутий кеш з TTL, max size тощо.


8. Коли мемоізацію не варто використовувати

  • Функція майже миттєва (дешеві обчислення);
  • Аргументи щоразу різні (немає сенсу кешувати);
  • Пам'ять обмежена (занадто великий кеш може "з'їсти" RAM);
  • У функції є побічні ефекти (HTTP-запит, зміна зовнішніх даних).

Короткий підсумок

Що цеНавіщоКоли використовувати
Кешування результатів функціїПрискорює повторні обчисленняПри частих викликах з тими самими аргументами
Працює для "чистих" функційБез побічних ефектівКоли обчислення дорогі
Не підходить для непередбачуваних вхідних данихНемає повторів - немає користі-

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.