Fundamentals 9 min read

Master Functional Programming in JavaScript: Currying, Pipe, Compose

This article introduces functional programming fundamentals, showcases common JavaScript scenarios like map/filter/reduce, explains key concepts such as first‑class functions, laziness, pure functions, currying, pipe, and compose, and demonstrates their practical application in a real‑world AgileBI report‑cell configuration system.

JD Cloud Developers
JD Cloud Developers
JD Cloud Developers
Master Functional Programming in JavaScript: Currying, Pipe, Compose

Function Programming Overview

Functional programming is a paradigm that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. In JavaScript it enables higher‑order functions, currying, composition, and lazy evaluation to write more reusable and declarative code.

Common Application Scenarios

ES6 array methods such as map, filter, reduce React class components transformed to functional components with hooks; Vue 3 composition API

Libraries like RxJS, Lodash, Ramda

Middleware/plug‑ins, e.g., Redux

applyMiddleware
[1,2,3,4,5].map(x => x * 2).filter(x => x > 5).reduce((p,n) => p + n);
const store = applyMiddleware(...middlewares)(createStore)(reducer, initialState);

What Is Functional Programming?

It abstracts programs into pure functions and immutable data structures, allowing functions to be passed as arguments and returned as results. In JavaScript it can emulate object‑oriented features such as abstraction, encapsulation, inheritance, and polymorphism while supporting higher‑order functions, currying, composition, and lazy evaluation.

Key Characteristics

First‑Class Functions

Functions can be passed to other functions and returned as values, enabling higher‑order functions.

Lazy Execution

Computations are deferred until their results are needed, improving performance by avoiding unnecessary work.

No Side Effects (Pure Functions)

Pure functions do not modify external state; they return the same output for the same input without causing side effects.

Common Functional Concepts

Currying

Transforms a function with multiple arguments into a sequence of functions each taking a single argument.

// Currying example
function curry(fn, args) {
  args = args || [];
  return function(...params) {
    const _args = [...args, ...params];
    if (_args.length < fn.length) {
      return curry(fn, _args);
    }
    return fn.apply(this, _args);
  };
}
function sum(a, b, c) { return a + b + c; }
const currySum = curry(sum);
console.log(currySum(1)(2)(3)); // 6
console.log(currySum(1)(2, 3)); // 6
console.log(currySum(1, 2)(3)); // 6

Pipe

The pipe function composes functions left‑to‑right, passing each result to the next.

export const pipe = (...fns) => input =>
  fns.reduce((chain, fn) => chain.then(fn), Promise.resolve(input));

Compose

The compose function composes functions right‑to‑left.

export const compose = (...fns) => input =>
  fns.reduceRight((chain, fn) => chain.then(fn), Promise.resolve(input));

Practical Case: AgileBI Cell Configuration

AgileBI is an online reporting tool that allows drag‑and‑drop creation of complex reports. A new requirement adds batch configuration for cells, supporting expansion direction, parent cell linking, and full configuration for text, field, and formula cells.

The implementation uses higher‑order handlers for each configuration aspect and a custom pipe to apply them sequentially.

private pipe = (...args) => {
  return (result, config) => {
    return args.reduce((acc, fn) => fn(acc, config), result);
  };
};

// Example handlers
private handleExpand(expandConf) {
  return conf => {
    if (expandConf) conf.expandDirection = expandConf;
    return conf;
  };
}
private handleParentCell(columnParentCell, rowParentCell) {
  return conf => {
    if (columnParentCell?.parentSelectType) conf.columnParentCell = columnParentCell;
    if (rowParentCell?.parentSelectType) conf.rowParentCell = rowParentCell;
    return conf;
  };
}
// ... other handlers (format, filter, condition)

let handles = [];
if (cell?.dataConf?.cellType === "文本") {
  handles = [this.handleExpand(conf.expandDirection), this.handleParentCell(conf.columnParentCell, conf.rowParentCell)];
} else if (cell?.dataConf?.cellType === "字段" || cell?.dataConf?.cellType === "公式") {
  handles = [
    this.handleExpand(conf.expandDirection),
    this.handleParentCell(conf.columnParentCell, conf.rowParentCell),
    this.handleFormat(conf.dataFormatConf),
    this.handleFilter(conf.cellFilterConf),
    this.handleCondition(conf.conditionConf)
  ];
}
if (handles.length > 0) {
  const mergeConf = this.pipe(...handles)(JSON.parse(JSON.stringify(cell.dataConf)));
  // apply mergeConf …
}

Conclusion

Functional programming improves code reusability and reduces duplicate development effort.

It enhances readability, making code easier to understand and debug.

Function composition simplifies maintenance and promotes modular design.

Composition is often preferable to inheritance.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptfunctional programmingComposeHigher-Order FunctionsCurryingPipe
JD Cloud Developers
Written by

JD Cloud Developers

JD Cloud Developers (Developer of JD Technology) is a JD Technology Group platform offering technical sharing and communication for AI, cloud computing, IoT and related developers. It publishes JD product technical information, industry content, and tech event news. Embrace technology and partner with developers to envision the future.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.