Что делать в функции каррирования в JavaScript при получении достаточного количества аргументов
Что проверяют
Владение замыканиями, остаточными параметрами и свойством length у функции. Задача почти всегда пишется при интервьюере, поэтому оценивают не только итоговый код, но и то, как вы рассуждаете про накопление аргументов и про условие остановки.
Как отвечать
Условие простое: как только накопленных аргументов хватает на исходную функцию, её нужно вызвать и вернуть результат. Пока не хватает, возвращается новая функция, которая продолжит накапливать.
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) return fn.apply(this, args);
return (...rest) => curried.apply(this, args.concat(rest));
};
}
const add = (a, b, c) => a + b + c;
const sum = curry(add);
sum(1)(2)(3); // 6
sum(1, 2)(3); // 6Проговорите две вещи: почему сравнение через >=, а не через равенство, и почему промежуточное значение это функция, которая помнит уже полученные аргументы в замыкании. Если каррируемая функция может быть методом, контекст прокидывают через apply, а стрелка внутри берёт this из окружения.
Где спотыкаются
Пишут строгое равенство args.length === fn.length. Один лишний аргумент, и вызов никогда не случится: функция бесконечно возвращает саму себя. Нужно либо сравнение с запасом, либо явная обрезка лишних аргументов.
Слепо полагаются на fn.length, не зная его правил. В это число не входят параметры со значением по умолчанию и остаточный параметр, поэтому у (a, b = 1, c) => {} оно равно единице, а у функции на ...args нулю. Для таких случаев нужную арность передают вторым параметром curry.
Путают каррирование с частичным применением. В строгом определении каррирование это цепочка вызовов ровно по одному аргументу, а приведённая реализация допускает sum(1, 2)(3). Скажите это вслух сами: вопрос часто и задают, чтобы поймать разницу.