Advanced Closures & Currying

📖 Concept

Currying transforms a function that takes multiple arguments into a sequence of functions each taking a single argument: f(a, b, c)f(a)(b)(c).

Partial Application fixes some arguments of a function, producing a function with fewer arguments.

Both leverage closures to "remember" previously supplied arguments.

🏠 Real-world analogy: Currying is like a burger assembly line. Station 1 adds the bun (first arg). Station 2 adds the patty (second arg). Station 3 adds toppings (third arg). Each station remembers what was added before.

💻 Code Example

codeTap to expand ⛶
1// Basic currying
2function curry(fn) {
3 return function curried(...args) {
4 if (args.length >= fn.length) {
5 return fn.apply(this, args);
6 }
7 return function(...args2) {
8 return curried.apply(this, args.concat(args2));
9 };
10 };
11}
12
13const add = (a, b, c) => a + b + c;
14const curriedAdd = curry(add);
15console.log(curriedAdd(1)(2)(3)); // 6
16console.log(curriedAdd(1, 2)(3)); // 6
17console.log(curriedAdd(1)(2, 3)); // 6
18
19// Practical currying
20const multiply = curry((a, b) => a * b);
21const double = multiply(2);
22const triple = multiply(3);
23console.log([1,2,3].map(double)); // [2, 4, 6]
24
25// Partial application
26function partial(fn, ...presetArgs) {
27 return function(...laterArgs) {
28 return fn(...presetArgs, ...laterArgs);
29 };
30}
31const addTax = partial(multiply, 1.2);
32console.log(addTax(100)); // 120
33
34// Advanced closure: function composition with currying
35const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
36const processPrice = pipe(
37 multiply(1.2), // Add 20% tax
38 (x) => x.toFixed(2), // Format
39 (x) => `$${x}` // Add currency
40);
41console.log(processPrice(100)); // "$120.00"

🏋️ Practice Exercise

Mini Exercise:

  1. Implement a generic curry function that handles any number of arguments
  2. Create a curried logger(level)(module)(message) function
  3. Build a curried API query builder: query(table)(fields)(conditions)
  4. Implement partial and partialRight functions

⚠️ Common Mistakes

  • Currying only works when function's .length is accurate — rest params and defaults break this

  • Over-currying simple functions makes code harder to read — use it when it provides clear benefits

  • Confusing currying (one arg at a time) with partial application (fixing some args upfront)

  • Memory overhead — each curried call creates a new closure in memory

  • Not understanding that arrow functions with defaults have .length of 0 for defaulted params

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for Advanced Closures & Currying. Login to unlock this feature.