Что такое каррирование в JavaScript

«Что такое каррирование в JavaScript» — вопрос из категории JavaScript, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Базовый пример:

// Обычная функция
const add = (a, b, c) => a + b + c;

// Каррированная версия
const curriedAdd = a => b => c => a + b + c;

console.log(add(1, 2, 3));        // 6
console.log(curriedAdd(1)(2)(3)); // 6

Практическое применение в Node.js:

// Каррирование для создания middleware с конфигурацией
const createLogger = (serviceName) => (logLevel) => (message) => {
  console.log(`[${serviceName}] [${logLevel.toUpperCase()}] ${message}`);
};

const authServiceLogger = createLogger('AuthService');
const authErrorLogger = authServiceLogger('error');
const authInfoLogger = authServiceLogger('info');

// Использование специализированных логгеров
authErrorLogger('Invalid token provided'); // [AuthService] [ERROR] Invalid token provided
authInfoLogger('User login successful');   // [AuthService] [INFO] User login successful

// Каррирование для работы с базами данных
const createQuery = (dbClient) => (tableName) => (conditions) => {
  return dbClient.query(`SELECT * FROM ${tableName} WHERE ?`, [conditions]);
};

const queryUsers = createQuery(dbClient)('users');
const activeUsersQuery = queryUsers({ status: 'active' });
// activeUsersQuery - готовая к выполнению функция с предустановленными параметрами

Утилита для каррирования:

// Универсальная функция каррирования
function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      };
    }
  };
}

// Использование
const multiply = (a, b, c) => a * b * c;
const curriedMultiply = curry(multiply);

const double = curriedMultiply(2);
const doubleAndTriple = double(3);

console.log(doubleAndTriple(4)); // 24 (2 * 3 * 4)

Преимущества каррирования в Node.js:

  1. Переиспользование кода: Создание специализированных функций из общих
  2. Композиция: Упрощает создание цепочек вызовов и композицию функций
  3. Отложенное выполнение: Можно подготовить функцию с частью аргументов и выполнить позже
  4. Чистые функции: Каррированные функции легче тестировать и отлаживать