В JavaScript очень легко дублировать одно и то же условие в разных местах. Сначала мы пишем общий filter, потом второй, потом третий почти такой же, а через месяц уже неясно, где одинаковая логика, а где начало расхождения.

Partial application помогает не копировать такие куски заново. Мы берем общую функцию, фиксируем часть аргументов и получаем новую, более конкретную функцию с понятным назначением.

Это не про “магическое” функциональное программирование. Это про то, как превращать слишком общие функции в говорящие предикаты и удобные строительные блоки.

Обновлено 17 марта 2026: переписаны примеры, убраны нерабочие фрагменты и уточнено различие между partial application, currying и bind.

Чем partial application отличается от currying

Эти термины часто смешивают, но это не одно и то же.

  • currying преобразует функцию с несколькими аргументами в цепочку функций по одному аргументу;
  • partial application фиксирует часть аргументов и возвращает новую функцию, которая ждет остальные.

Currying часто делает partial application удобнее, но частичное применение возможно и без каррирования.

Если хочешь глубже разобрать сам currying, посмотри Каррирование функций в JavaScript.

Самый полезный сценарий: говорящие предикаты

Допустим, у нас есть общая функция, которая проверяет тип задачи.

function isTaskOfType(type, task) {
  return task.type === type;
}

Вызов напрямую выглядит слишком общо:

tasks.filter((task) => isTaskOfType("NC", task));

С частичным применением можно зафиксировать тип один раз и получить функцию, которая уже отражает смысл.

const partial = (fn, fixedArg) => (value) => fn(fixedArg, value);

function isTaskOfType(type, task) {
  return task.type === type;
}

const isNewContentTask = partial(isTaskOfType, "NC");

tasks.filter(isNewContentTask);

Разница не только в краткости. isNewContentTask хорошо читается в любом месте кода и снижает риск, что ты начнешь копировать строковый литерал "NC" по проекту.

Partial application через замыкание

На практике partial application часто выглядит просто как функция, которая возвращает другую функцию и хранит заранее переданное значение в замыкании.

const withPrefix = (prefix) => (message) => `${prefix}: ${message}`;

const asError = withPrefix("Error");
const asInfo = withPrefix("Info");

console.log(asError("Missing config")); // Error: Missing config
console.log(asInfo("Server started")); // Info: Server started

Здесь prefix зафиксирован заранее. Каждая новая функция переиспользует эту часть конфигурации без повторения.

Partial application в реальном коде

Обычно этот прием полезен в трех местах:

Фильтрация и поиск

Когда один и тот же критерий используется во многих filter, find или some.

Настройка API и адаптеров

Когда нужно один раз зафиксировать baseUrl, feature flag, logger или формат данных.

Подготовка функций для композиции

Когда ты хочешь собрать pipeline из маленьких шагов и заранее подставить конфигурацию.

Например:

const map = (fn) => (list) => list.map(fn);
const prop = (key) => (obj) => obj[key];

const getName = prop("name");
const getNames = map(getName);

getNames([
  { name: "Alex" },
  { name: "Julia" },
]); // ["Alex", "Julia"]

Здесь partial application делает маленькие функции переиспользуемыми и готовыми к композиции.

Когда достаточно bind

Иногда partial application не требует собственной утилиты. В простых случаях хватает bind.

const multiply = (x, y) => x * y;

const multiplyBy2 = multiply.bind(null, 2);

multiplyBy2(3); // 6
multiplyBy2(5); // 10

bind удобен, когда ты работаешь с обычной функцией и хочешь быстро зафиксировать первые аргументы. Но если код уже строится вокруг композиции, каррированных функций и data-last сигнатур, собственные небольшие утилиты часто читаются лучше.

Ошибки, которые делают partial application бесполезным

Частичное применение не помогает автоматически. Его легко превратить в еще один слой сложности.

Осторожнее, если:

  • новая функция получила абстрактное имя и перестала объяснять смысл;
  • partial application используется один раз и только скрывает простой аргумент;
  • ради красивой формы приходится угадывать порядок аргументов;
  • данные передаются не последним аргументом и функцию неудобно собирать в pipeline.

Самый хороший результат получается там, где новая функция начинает читаться как отдельное правило домена.

Partial application полезен тогда, когда помогает превратить слишком общую функцию в конкретную и говорящую. Он снижает копипасту, делает код легче для чтения и хорошо работает вместе с замыканиями, bind и функциональной композицией.

Если нужен быстрый ориентир, ищи повторяющиеся условия и повторяющуюся конфигурацию. Именно там partial application почти всегда окупается.