Explorer
JavaScript

compose and pipe in js

JavaScript Theory & Concepts

Compose and Pipe in JavaScript

Functional pipeline architecture, unary composition, and point-free coding style.

📖 The Story & Real-World Analogy

The Manufacturing Factory Conveyor Belt

"Think of an automated artisan toy workshop. A raw block of pine wood enters a conveyor belt with three specialized stations: 1. Station A planes and sands the block (`sand`). 2. Station B paints it royal blue (`paint`). 3. Station C stamps a gold star on it (`stamp`). • **Pipe**: Reads in the natural manufacturing order left-to-right (`pipe(sand, paint, stamp)`). • **Compose**: Follows formal mathematical function notation f(g(h(x))), evaluating from the inside out / right-to-left (`compose(stamp, paint, sand)`)."

Function composition combines multiple simple functions to build complex transformations. Output of each function becomes the input of the next, producing clean, declarative pipelines.

⚙️ How It Works Under The Hood (Step-by-Step)
1

Mathematical Foundation

Given two functions f and g, composition is (f \circ g)(x) = f(g(x)). The innermost function evaluates first.

2

Unary Constraint

Functions in a pipeline must be unary (accept a single argument). Multi-argument functions should be curried first before entering the pipeline.

3

Implementing pipe() with reduce

`const pipe = (...fns) => (x) => fns.reduce((val, fn) => fn(val), x)`. Left-to-right execution flow.

4

Implementing compose() with reduceRight

`const compose = (...fns) => (x) => fns.reduceRight((val, fn) => fn(val), x)`. Right-to-left execution flow.

💻 Interactive Code Walkthrough

Building pipe and compose to format and sanitize user input data:

JAVASCRIPT
const trim = (str) => str.trim();
const toLowerCase = (str) => str.toLowerCase();
const wrapInTag = (tag) => (content) => `<${tag}>${content}</${tag}>`;

// Implementations
const pipe = (...fns) => (initialValue) =>
  fns.reduce((acc, fn) => fn(acc), initialValue);

const compose = (...fns) => (initialValue) =>
  fns.reduceRight((acc, fn) => fn(acc), initialValue);

// Clean text pipeline
const sanitizeUsername = pipe(
  trim,
  toLowerCase,
  wrapInTag("span")
);

const mathCompose = compose(
  (x) => x * 2,    // 3. Multiplies 6 * 2 = 12
  (x) => x + 1,    // 2. Adds 5 + 1 = 6
  (x) => Math.abs(x) // 1. Abs(-5) = 5
);

console.log(sanitizeUsername("   Alex_Dev   "));
console.log("Math compose result:", mathCompose(-5));
Console Output:
CODE
<span>alex_dev</span>
Math compose result: 12
⚠️ Common Pitfalls & Interview Traps
Trap
Passing Impure or Mutating Functions into Pipeline

The Risk: If a function inside a pipe mutates its input in-place instead of returning a new value, side effects pollute subsequent operations.

The Fix: Ensure every function in a compose/pipe pipeline is a pure function that returns a new value.

⚡ 30-Second Quick Revision Cheat Sheet (TL;DR)
  • ✓ `pipe()` evaluates Left-to-Right (natural reading order, uses `reduce`).
  • ✓ `compose()` evaluates Right-to-Left (mathematical order, uses `reduceRight`).
  • ✓ All pipeline functions must be unary (one argument in, one argument out).
  • ✓ Use currying to adapt multi-argument functions into the pipeline.
  • ✓ Enables clean "point-free" programming style.

Finished this lesson?

Mark this chapter complete to update your learning streak and unlock the next lesson.