![]() |
If you're learning JavaScript, you've probably already encountered two fundamental concepts: closure and currying. But there's a moment where something doesn't add up: the examples explaining currying... look identical to those explaining closures!
Spoiler: This is not a coincidence. In fact, currying relies on closures to work. In this article, we'll explore the connection between the two concepts, see clear examples, and understand how to use them effectively.
๐ง Closure: the function that remembers everything
A closure is a function that "remembers" the variables of the context in which it was created, even if that context no longer exists.
๐ Example:
function greet(name) {
return function(message) {
console.log(`${message}, ${name}`);
};
}
const greetMarco = greet("Marco");
greetMarco("Hello"); // Output: Hello, Marco
Here, greetMarco
is a closure: it retains the value of name
even after greet
has finished executing.
๐ Currying: One Function at a Time
Currying is a functional programming technique. It consists of transforming a function that takes multiple arguments into a series of functions that take a single argument.
๐ Example:
function sum(a) {
return function(b) {
return a + b;
};
}
const sum5 = sum(5);
console.log(sum5(3)); // Output: 8
Here we've curried a two-argument function (a
, b
) into two nested functions, each with a single argument.
๐ฏ Do they look the same? Of course!
The similarity is no coincidence: currying works precisely thanks to closures. When you call sum(5)
, JavaScript creates a function that remembers the value of a
thanks to a closure. When you then call sum5(3)
, that value is retrieved from the closed context.
๐ In other words:
All curried functions are closures. But not all closures are curried.
But what does that really mean? Let's look at a practical example of a closure that isn't currying.
✅ Example:
function createCounter() {
let counter = 0;
return function() {
counter++;
console.log(`Counter: ${counter}`);
};
}
const increment = createCounter();
increment(); // Counter: 1
increment(); // Counter: 2
The inner function returned by createCounter
is a closure because it retains access to the counter
variable, even after the outer function has terminated.
But it's not currying: it doesn't break parameters into nested functions, it doesn't manage a sequence of arguments—it simply maintains private state.
๐ Comparison: A curried function
function multiply(a) {
return function(b) {
return a * b;
};
}
const per2 = multiply(2);
console.log(per2(5)); // 10
This instead is:
- a closure (remember the value of
a
) - and curried, because it transforms
multiply(a, b)
intomultiply(a)(b)
๐ง In summary
Type | Closure? | Curried? |
---|---|---|
createCounter() |
✅ Yes | ❌ No |
multiply(a)(b) |
✅ Yes | ✅ Yes |
In short: Currying is a specific use of closures, but closures can serve a variety of other purposes, such as maintaining state, creating private APIs, or configuring behaviors.
๐งช Difference in brief
Concept | Closure | Currying |
---|---|---|
What is it? | A function that remembers its scope. | A technique for dividing a function into multiple steps. |
Purpose. | Encapsulating state and context. | Composition, partial application. Reusability |
Classic example | greetMarco("Hello") |
sum(5)(3) |
๐ ️ When to use what?
- Use closures to:
- maintain private state
- create configurable functions
- avoid global variables
- Use currying to:
- Compose functions
- Create reusable functions
- Improve readability and flexibility
๐ Conclusion
Closure and currying are two powerful tools in your JavaScript arsenal. Understanding that currying is built on closures allows you to master both concepts more naturally.
Follow me #techelopment
Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment