February 16

Композиция функций. Задача Javascript.

Условие задачи:

Напишите функцию compose, которая принимает произвольное количество функций и возвращает новую функцию. Новая функция должна применять переданные функции в порядке обратном их указанию, передавая результат каждой следующей функции.
Требования:

  • Поддержка функций с разным количеством аргументов
  • Первая функция в цепочке может принимать несколько аргументов
  • Примеры:
    • compose(f, g)(x)f(g(x))
    • compose(a, b, c)(1, 2)a(b(c(1, 2)))

Решение:

https://codepen.io/TimofeevAlexey/pen/ZYEENWj

// Базовые функции-примеры
const square = (x) => x * x;     // Возводит в квадрат
const times2 = (x) => x * 2;     // Умножает на 2
const sum = (a, b) => a + b;     // Суммирует два числа

/**
 * Создает композицию функций, применяя их справа налево.
 * @param {...Function} funcs - Функции для композиции
 * @returns {Function} Новая функция, применяющая цепочку преобразований
 */
const compose = (...funcs) => {
  const composedFunction = (...initialArgs) => {
    let currentResult;
    let functionIndex = funcs.length - 1; // Начинаем с последней функции
    
    // Проходим все функции в обратном порядке
    while (functionIndex >= 0) {
      const currentFunc = funcs[functionIndex];
      
      if (currentResult === undefined) {
        // Первый вызов: передаем все аргументы в последнюю функцию
        currentResult = currentFunc(...initialArgs);
      } else {
        // Последующие вызовы: передаем результат предыдущей функции
        currentResult = currentFunc(currentResult);
      }
      
      functionIndex--;
    }
    
    return currentResult;
  };
  
  return composedFunction;
};

// Примеры использования
console.log(compose(square, times2)(2));          // 16 (2 → times2(4) → square(16))
console.log(compose(square, times2, sum)(3, 4));  // 196 (sum(3+4=7) → times2(14) → square(196))

Ключевые особенности

Порядок выполнения:

compose(f1, f2, f3)f1(f2(f3(...args)))

Обработка аргументов:

Первая функция в цепочке (последняя в funcs) получает все исходные аргументы

Инициализация результата: Используется undefined для определения первого шага

Визуализация работы
Для compose(square, times2, sum)(3, 4):

Copy

Шаг 1: sum(3, 4) → 7  
Шаг 2: times2(7) → 14  
Шаг 3: square(14) → 196  

Частые ошибки новичков

  • Неправильный порядок функций: Ожидают, что compose(f, g) выполнит g(f(x)) вместо f(g(x)).
  • Потеря аргументов: Неправильная передача ...initialArgs только в первую функцию.
  • Мутация данных: Изменение исходных аргументов внутри функций.

Дополнительные задания

  1. Реализуйте pipe — версию compose с порядком выполнения слева направо.
  2. Добавьте обработку асинхронных функций.
  3. Разрешите передачу значений разных типов (например, строковые операции).
  4. Сравните производительность с вложенными вызовами: f(g(h(x))) vs compose(f, g, h)(x).