> Как реализовать функцию memo для кеширования результатов вызовов по аргументам в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: 1221 Systems

Стек: JavaScript

> Пример ответа

Короткий ответ

Функция memo кеширует результаты вызовов на основе аргументов. Реализация включает хранение результатов в Map или WeakMap, где ключом выступает сериализованная строка аргументов или сам первый аргумент (для объектов). Важно учитывать ограничения: сериализация через JSON.stringify не работает с функциями, undefined, Symbol и циклическими ссылками. Для простых случаев используют строковое представление, для сложных - кастомные хеш-функции или WeakMap для объектных ключей.

Подробное объяснение

Memoization - это оптимизация, при которой результат вызова функции сохраняется и возвращается при повторном вызове с теми же аргументами. Основная цель - избежать повторных дорогостоящих вычислений.

Ключевые аспекты реализации:

  • Хранилище: обычно используется Map или объект. Для объектных аргументов, которые могут быть собраны сборщиком мусора, предпочтительнее WeakMap.
  • Ключ: сериализация аргументов в строку. Самый простой способ - JSON.stringify(arguments), но он не покрывает все типы (undefined, функции, Symbol). Альтернатива - кастомная сериализация или использование первого аргумента как ключа (если он уникальный объект).
  • Контекст: для методов объекта нужно учитывать this, иначе кеш будет общим для всех вызовов.
  • Ограничения: memoization не подходит для функций с побочными эффектами, недетерминированных функций (зависящих от времени, random) или функций с большим количеством уникальных аргументов (кеш будет расти бесконечно).

На практике

В реальных проектах memoization применяется для:

  • Вычислительно тяжелых чистых функций (например, сортировка, фильтрация больших массивов)
  • Результатов API-запросов (с осторожностью, так как данные могут устареть)
  • Рекурсивных алгоритмов (например, числа Фибоначчи, факториал)

Популярные библиотеки: lodash.memoize, reselect для Redux. В React - useMemo и memo для компонентов.

Важно: не мемоизировать функции, которые вызываются редко или с уникальными аргументами - overhead от кеширования может превысить выгоду.

Пример кода

JAVASCRIPT
function memo(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;
};
}
// Пример с WeakMap для объектных аргументов
function memoWeak(fn) {
const cache = new WeakMap();
return function(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
const result = fn.call(this, obj);
cache.set(obj, result);
return result;
};
}

Как отвечать на собеседовании

Начни с краткого определения memoization и его цели. Затем опиши базовую реализацию через Map и сериализацию аргументов. Обязательно упомяни ограничения: проблемы с объектами, циклическими ссылками, недетерминированными функциями. Предложи улучшения: WeakMap для объектов, кастомные хеш-функции, ограничение размера кеша (LRU cache). Покажи понимание trade-off между памятью и производительностью. Если спросят про контекст - объясни, что для методов нужно передавать this через apply или call.

Что проверяет интервьюер

  • Понимание концепции чистых функций и побочных эффектов
  • Умение работать с Map, WeakMap, сериализацией
  • Знание ограничений JSON.stringify
  • Понимание компромиссов между памятью и скоростью
  • Способность предложить оптимизации (LRU, ограничение размера кеша)
  • Умение учитывать контекст вызова (this)

Типичные ошибки

  • Использование объекта {} вместо Map (ключи только строки)
  • Игнорирование this при мемоизации методов
  • Сериализация через args.toString() или args.join(',') - не различает разные типы
  • Отсутствие обработки циклических ссылок в аргументах
  • Мемоизация функций с побочными эффектами или недетерминированных
  • Бесконечный рост кеша без ограничений (утечка памяти)
  • Использование JSON.stringify для аргументов, содержащих функции или undefined

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью