█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/Programming Languages/JavaScript (Standalone Deep Dive)/Functional Programming in JS
45 minIntermediate

Functional Programming in JS

After this lesson, you will be able to: Apply functional patterns: pure functions, immutability, map/filter/reduce, composition, partial application, currying.

FP in JS is everywhere (React, Redux, RxJS). Knowing the primitives unlocks the ecosystem.

Prerequisites:Prototypes

Pure functions + immutability

The two foundations.

tsx
// Pure: same input → same output; no side effects
const double = (x) => x * 2;
// Impure: depends on outer state
let counter = 0;
const inc = () => ++counter;
// Immutable update (key React pattern)
const user = { name: "Alex", age: 30 };
const older = { ...user, age: 31 }; // new object
const tags = ["a", "b"];
const more = [...tags, "c"]; // new array
const noB = tags.filter((t) => t !== "b"); // new array
const upper = tags.map((t) => t.toUpperCase());

map / filter / reduce

Replace most for-loops.

tsx
const orders = [{ total: 10 }, { total: 20 }, { total: 30 }];
const totals = orders.map((o) => o.total); // [10, 20, 30]
const big = orders.filter((o) => o.total > 15); // [{20}, {30}]
const sum = orders.reduce((s, o) => s + o.total, 0); // 60
// Chains read top-to-bottom
const result = orders
.filter((o) => o.total > 15)
.map((o) => o.total * 1.1)
.reduce((s, t) => s + t, 0);

Composition + partial + currying

Less common in plain JS but useful idioms.

tsx
// Composition: f(g(x))
const compose = (...fns) => (x) => fns.reduceRight((acc, fn) => fn(acc), x);
const addOne = (x) => x + 1;
const double = (x) => x * 2;
const f = compose(addOne, double); // addOne(double(x))
f(3); // 7
// Partial application
const add = (a, b, c) => a + b + c;
const addFromTen = (b, c) => add(10, b, c);
// or use Function.prototype.bind
const addFromTen2 = add.bind(null, 10);
// Currying
const curry = (a) => (b) => (c) => a + b + c;
curry(1)(2)(3); // 6

When functional, when not

FP wins for: data transformation pipelines, React state updates, predictable testing. Imperative wins for: tight performance loops, low-level I/O, mutation-heavy algorithms. Don't dogma, mix freely.

💡 Recursion goes hand in hand with FP

Functional code leans on recursion in place of mutable loops: a function that calls itself, with a base case and a recursive case. The mechanics (the call stack, base cases, tail recursion, and when iteration is the better choice) are covered in depth in the Computer Science Fundamentals > Algorithms recursion lesson. Work through it if recursive solutions still feel like magic.

Common mistakes only experienced JS devs avoid

Mutating arrays inside map/filter/reduce. The callback should be pure. Using reduce when forEach is clearer. Reduce is overrated. Excessive currying. JS isn't Haskell; don't fight the language. Forgetting that array methods like sort() mutate. Use [...arr].sort() if you need immutability.

Quick Check

Why is `arr.sort()` a footgun?

Pick the cleanest answer.

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←Prototypes and the Prototype Chain
Back to JavaScript (Standalone Deep Dive)
Browser vs Node Runtimes→