An Introduction to Closures and Currying in JavaScript
Practical guide to JavaScript closures: definition, lexical environment, module pattern, function factories, currying, and examples.
Drake Nguyen
Founder · System Architect
Introduction
If you write JavaScript, you will often hear the term "javascript closures". They are a core concept in the language that enable powerful patterns such as encapsulation, function factories and currying. This article answers the common question "what is a closure in javascript" and shows javascript closures explained with examples you can try.
A closure is a combination of a function and the lexical environment in which it was declared.
Put another way, a closure gives a function access to variables from its outer (enclosing) scope even after that outer function has finished executing. This behavior stems from lexical scope in JavaScript: inner functions keep references to free variables that were present when they were created.
Closure fundamentals
To understand closures you need to know about function scope javascript and lexical environment javascript maintains at creation time. When a function is defined it captures references to variables in its outer scope (the scope chain). Those captured variables remain available to the inner function, creating the closure scope that preserves state.
Simple closure example
// closure in javascript simple example
function makeAdder(x) {
return function(y) {
return x + y; // inner function references x from outer scope
};
}
const add5 = makeAdder(5);
console.log(add5(3)); // 8
console.log(makeAdder(10)(2)); // 12 (immediately invoked inner function)
Here makeAdder is a function factory javascript: it produces new functions that remember the value of x. That demonstrates how closures can create private state and reuse behavior.
Why use closures?
Closures have several practical uses and advantages:
- Encapsulation: create private variables without exposing them globally (javascript closure module pattern example).
- Function factories: produce specialized functions (function factory closure javascript) such as adders or formatters.
- Functional patterns: implement currying and partial application (currying in javascript, currying vs partial application javascript).
- Maintain state across asynchronous callbacks without global variables.
Module pattern and private variables
Before ES6 classes, the module pattern javascript was a common way to emulate private members using closures. It keeps implementation details hidden while exposing a public API.
// javascript closure module pattern example (ES5 style)
function createCounter() {
let count = 0; // private variable
function changeBy(delta) {
count += delta;
}
return {
increment: function() { changeBy(1); },
decrement: function() { changeBy(-1); },
value: function() { return count; }
};
}
const counter1 = createCounter();
const counter2 = createCounter();
console.log(counter1.value()); // 0
counter1.increment();
counter1.increment();
console.log(counter1.value()); // 2
console.log(counter2.value()); // 0 (separate closure)
This demonstrates how closures create independent private state for each instance, similar to objects with private fields.
Currying and functional programming
Currying in JavaScript transforms a function of multiple arguments into a sequence of functions that each take a single argument. Curry techniques rely on closures to capture earlier arguments. Currying is common in functional programming javascript and pairs well with higher-order functions and composition.
Currying example
// currying in javascript (ES6 arrow functions)
const greeting = a => b => `${a} ${b}`;
const hello = greeting('Hello');
console.log(hello('Austin')); // Hello Austin
console.log(greeting('Good morning')('Roy')); // Good morning Roy
// simple curry helper
const curry = fn =>
(...args) =>
args.length >= fn.length ? fn(...args) : (...more) => curry(fn)(...args, ...more);
const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // 6
Currying vs partial application javascript: currying converts a multi-argument function into nested single-argument functions, while partial application fixes a few arguments and returns a function that accepts the remaining ones. Both techniques typically use closures.
Practical tips and gotchas
- Be mindful of memory: closures keep references to outer variables, which can prolong their lifetime until the closure is garbage-collected.
- When using loops, prefer let over var to avoid common closure-in-loop bugs caused by function scope javascript.
- Use closures for encapsulation or function factories, but prefer clear APIs (classes or modules) when readability is more important.
Conclusion
Javascript closures are an essential language feature that link functions with their lexical environment. Whether youre creating private variables with closures javascript, building function factories, or implementing currying in javascript, closures enable flexible, reusable patterns. Understanding closures and lexical scoping will strengthen your grasp of scope chain, inner function behavior, and many functional programming techniques in JavaScript.