> Как реализовать мемоизацию функции в JavaScript (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Домклик
Стек: JavaScript
> Пример ответа
Короткий ответ
Мемоизация - это оптимизация, при которой функция кэширует результаты выполнения для уникальных аргументов. Реализуется через замыкание, хранящее Map или WeakMap. При вызове проверяется, есть ли результат для переданных аргументов: если да - возвращается из кэша, если нет - вычисляется и сохраняется. Для функций с несколькими аргументами ключом может быть строка из сериализованных аргументов.
Подробное объяснение
Мемоизация основана на принципе чистой функции: при одинаковых входных данных результат всегда одинаков. Это позволяет избежать повторных вычислений для дорогих операций (рекурсия, сложные алгоритмы, запросы к API).
Базовая реализация использует замыкание с объектом-кэшем. Ключом выступает строка, полученная через JSON.stringify(args). Для одного аргумента можно использовать сам аргумент как ключ. Важный trade-off: мемоизация увеличивает потребление памяти за счёт хранения результатов.
Для рекурсивных функций (например, вычисление чисел Фибоначчи) мемоизация даёт экспоненциальный прирост производительности - сложность падает с O(2^n) до O(n). Однако мемоизация неэффективна для функций с побочными эффектами, недетерминированных функций (random, Date.now) или при редком повторении одинаковых аргументов.
На практике
В продакшене часто используют готовые решения: _.memoize из lodash или useMemo/useCallback в React. Но для понимания важно уметь написать свою реализацию.
Ключевые моменты:
- Для сериализации аргументов используйте
JSON.stringify- он обрабатывает объекты, массивы, примитивы - Учитывайте, что порядок ключей объекта влияет на сериализацию
- Для методов класса нужна осторожность: контекст
thisможет меняться - Можно добавить ограничение размера кэша (LRU-кэш) для предотвращения утечек памяти
Пример кода
JAVASCRIPTfunction memoize(fn) {const cache = new Map();return function(...args) {const key = JSON.stringify(args);if (cache.has(key)) {return cache.get(key);}const result = fn.apply(this, args);cache.set(key, result);return result;};}// Пример с рекурсиейconst fib = memoize(function(n) {if (n <= 1) return n;return fib(n - 1) + fib(n - 2);});console.log(fib(40)); // 102334155 - мгновенно
Как отвечать на собеседовании
Начните с определения мемоизации и её цели. Объясните механизм через замыкание и кэш. Упомяните trade-off между скоростью и памятью. Приведите пример, где мемоизация даёт значительный выигрыш (Фибоначчи, факториал). Упомяните ограничения: недетерминированные функции, побочные эффекты, сериализация объектов. Если спросят про WeakMap - объясните, что он не подходит, так как ключи могут быть собраны сборщиком мусора.
Что проверяет интервьюер
- Понимание замыканий и области видимости
- Умение работать с Map и сериализацией
- Знание принципов функционального программирования (чистые функции)
- Понимание компромиссов (time vs memory)
- Способность предвидеть edge cases (this, рекурсия, объекты как аргументы)
Типичные ошибки
- Использование объекта
{}вместо Map - ключи приводятся к строке, что ломает работу с объектами - Игнорирование контекста
this- при мемоизации методов класса теряется привязка - Отсутствие сериализации для нескольких аргументов - ключом становится только первый аргумент
- Мемоизация нечистых функций - результат может быть неверным при побочных эффектах
- Бесконтрольный рост кэша без ограничения размера - утечка памяти в долгоживущих приложениях
> Похожие задачи по frontend
Как решать задачу анимации шаг за шагом
Реализовать функцию, принимающую массив промисов и возвращающую массив результатов или первый reject в JavaScript
Как реализовать функцию retry для повторного вызова асинхронной функции при ошибке в JavaScript
Как обрабатывать дублирующиеся ключи при преобразовании массива объектов в объект в JavaScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью