*What is currying, and how do closures make it possible in JavaScript? *
Currying is hot topic in frontend interview,it is usually the next question after closure because it is an example. Recently i got hit with the INFINITE CURRYING Question. Here is full detail
⚙️ Practical Benefit of Currying:
- Delays execution until all arguments are provided
- Enables function reusability (partial application)
Function currying is when functions are nested. This helps us to execute partially functions if there is a requirement of waiting. Example to add two number using curring
function add() {
function arg1(a) {
function arg2(b) {
return a+b
}
return arg2
}
return arg1
}
// this returns arg1
const addnum = add()
// this takes first input and return arg2
const firstArg = add(2);
// taken second input and returns the sum
const final = firstArg(3)
✅ Clean Curried Add Example:
function add(a) {
return function(b) {
return a + b;
};
}
console.log(add(2)(3)); // Output: 5
Explanation:
add(2) returns a closure that remembers a = 2
That returned function takes b and adds it to a.
Now if we think the above examples are quite commom. but what about infinite curring? Below is the example of it-
Can we write a function like add(1)(2)(3)...(n) that returns the sum when we call .value() or even when coerced?
🧩 Infinite Currying:
- You need to return a function every time, so chaining like add(1)(2)(3)... works.
- To get the final result, you’ll use: .valueOf() or .toString() for coercion (console.log(add(1)(2)(3))) OR an explicit .value() method.
- Use a closure to keep the running sum.
function add(a) {
let sum = a;
function inner(b) {
if (b !== undefined) {
sum += b;
return inner; // keep returning the function for chaining
}
return sum; // fallback, if no argument is passed
}
inner.valueOf = function () {
return sum;
};
inner.toString = function () {
return sum.toString();
};
return inner;
}
console.log(+add(1)(2)(3)); // 6
console.log(add(5)(10)(15) + 0); // 30
inner.value = () => sum;
📜 1.Another example by arbitrary argument counts in each call? Like:
add(1, 2)(3, 4)(5)(6) // → 21
Solution-
function sum(...initialArgs) {
let storage = [...initialArgs];
function inner(...nextArgs) {
storage.push(...nextArgs);
return inner;
}
inner.valueOf = function () {
return storage.reduce((a, b) => a + b, 0);
};
inner.toString = function () {
return this.valueOf().toString();
};
inner.value = function () {
return this.valueOf();
};
return inner;
}
📜 2. Add History Tracking (Bonus Closure Feature)
function sumWithHistory(...initialArgs) {
let storage = [...initialArgs];
function inner(...nextArgs) {
if (nextArgs.length === 0) {
return storage.reduce((a, b) => a + b, 0);
}
storage.push(...nextArgs);
return inner;
}
inner.valueOf = function () {
return storage.reduce((a, b) => a + b, 0);
};
inner.toString = function () {
return this.valueOf().toString();
};
inner.value = function () {
return this.valueOf();
};
inner.history = function () {
return [...storage];
};
return inner;
}
const s = sumWithHistory(1)(2, 3)(4);
console.log(s.value()); // 10
console.log(s.history()); // [1, 2, 3, 4]
we can combine these into a reusable curry utility that can handle any reducer function (e.g., sum, product, max, etc.)!
Top comments (0)