> Как реализовать функцию add в JavaScript, которая накапливает аргументы и возвращает сумму при вызове без аргументов (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Домклик, Kaspersky
Стек: JavaScript
> Пример ответа
Короткий ответ
Функция add с накоплением аргументов и возвратом суммы при вызове без аргументов реализуется через замыкание и переопределение valueOf или Symbol.toPrimitive. При каждом вызове с аргументом она возвращает новую функцию, которая хранит текущую сумму в замыкании. При вызове без аргументов возвращается накопленное значение. Альтернативно можно использовать toString для неявного преобразования.
Подробное объяснение
Задача требует создания функции, которая ведет себя как add(1)(2)(3)() - возвращает 6. Ключевая идея - использовать замыкание для хранения аккумулятора. Каждый вызов с аргументом создает новую функцию, которая обновляет сумму и возвращает себя же (или новую функцию с обновленным значением). При вызове без аргументов возвращается финальная сумма.
Для поддержки цепочек вызовов без финального пустого вызова (например, add(1)(2)(3) возвращает 6) необходимо переопределить метод примитивного преобразования - valueOf или Symbol.toPrimitive. Это позволяет JavaScript автоматически преобразовывать функцию в число при контексте, ожидающем число (арифметические операции, сравнения, console.log).
Важно: функция должна быть чистой (без мутации глобального состояния) и поддерживать произвольное количество аргументов в одном вызове, например add(1, 2)(3)().
На практике
В реальных проектах такая конструкция редко встречается напрямую, но понимание замыканий, каррирования и примитивных преобразований критично для работы с функциональными библиотеками (Ramda, Lodash/fp), middleware (Redux), композиции функций и оптимизации вычислений.
Типичные сценарии использования:
- Ленивые вычисления с накоплением параметров
- Конфигураторы с fluent API (builder pattern)
- Функции-валидаторы с цепочками условий
Пример кода
JAVASCRIPTfunction add(...args) {const sum = args.reduce((acc, val) => acc + val, 0);function inner(...nextArgs) {if (nextArgs.length === 0) {return sum;}return add(sum, ...nextArgs);}inner.valueOf = () => sum;inner[Symbol.toPrimitive] = () => sum;return inner;}// Использованиеconsole.log(add(1)(2)(3)()); // 6console.log(add(1, 2)(3, 4)()); // 10console.log(add(5)(10) + 2); // 17 (через valueOf)console.log(add(1)(2)(3) == 6); // true (через Symbol.toPrimitive)
Как отвечать на собеседовании
- Начни с объяснения замыкания как основного механизма
- Покажи базовую реализацию с пустым вызовом в конце
- Объясни, как добавить поддержку неявного преобразования через
valueOf/Symbol.toPrimitive - Упомяни edge cases: вызов без аргументов сразу, передача нескольких аргументов, отрицательные числа
- Обсуди trade-off: рекурсивный подход vs итеративный, чистота функции, производительность при длинных цепочках
Что проверяет интервьюер
- Понимание замыканий и лексического окружения
- Знание механизмов приведения типов и примитивных преобразований
- Умение работать с rest parameters и spread operator
- Способность проектировать fluent API
- Понимание функционального программирования (каррирование, частичное применение)
- Внимание к деталям (обработка пустого вызова, множественных аргументов)
Типичные ошибки
- Использование глобальной переменной для хранения суммы (нарушение чистоты функции)
- Забывание обработать случай вызова без аргументов сразу (
add()) - Неправильное переопределение
valueOf- возврат функции вместо числа - Потеря контекста при использовании стрелочных функций в методах объекта
- Игнорирование множественных аргументов в одном вызове (
add(1, 2, 3)) - Создание бесконечной рекурсии при неправильной реализации цепочки
> Похожие задачи по frontend
Как обрабатывать случаи отклонения одного из промисов в Promise.all в JavaScript?
В чем разница package-lock.json и package.json
Что такое bind в JavaScript и как он работает
Что такое микрозадачи и макрозадачи
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью