How do JavaScript closures work?

How would you explain JavaScript closures to someone with a knowledge of the concepts they consist of (for example, functions, variables, and the like) but who does not understand closures themselves?

A closure is a pairing of:

A function and
A reference to that function’s outer scope (lexical environment)
A lexical climate is part of every execution context (stack frame) and is a map between identifiers (i.e., local variable names) and values.

Every function in JavaScript maintains a reference to its outer lexical environment. This reference configures the execution context created when a part is invoked. This reference enables code inside the process to “see” variables declared outside the process, regardless of when and where the process is called.

If a function was called by a process contacted by another method, then a chain of references to outer lexical environments is created. This chain is called the scope chain.

In the following code, inner forms a closure with the linguistic environment of the execution context created when foo is invoked, closing over variable secret:

function foo() {
const secret = Math.trunc(Math.random() * 100)
return function inner() {
console.log(`The secret number is ${secret}.`)
const f = foo() // `secret` is not directly accessible from outside `foo`
f() // The only way to retrieve `secret`, is to invoke `f`

Expand snippet
In other words: in JavaScript, functions refer to a private “box of state,” to which only they (and any other parts declared within the same linguistic environment) have access. This box of the state is invisible to the caller of the process, delivering an excellent mechanism for data hiding and encapsulation.

And remember: functions in JavaScript can be passed around like variables (first-class functions), meaning these pairings of functionality and state can be passed around your program: similar to how you might give an instance of a class around in C++.

If JavaScript did not have closures, then more states would have to be passed between functions explicitly, making parameter lists longer and code noisier.

So, you can use a closure if you want a function always to have access to a private state.

…and frequently, we do want to associate the state with a function. For example, in Java or C++, when you add a private instance variable and a method to a class, you associate the state with functionality.

In C and most other common languages, after a function returns, all the local variables are no longer accessible because the stack frame is destroyed. In JavaScript, if you declare a function within another part, the outer function’s local variables can remain accessible after returning from it. In this way, in the code above, the secret remains available to the function object inner after it has been produced from foo.

Uses of Closures
Closures are helpful whenever you need a private state associated with a function. This is a prevalent scenario – and remember: JavaScript did not have a class syntax until 2015, and it still does not have a private field syntax. Closures meet this need.

Private Instance Variables
The function toString closes over the car’s details in the following code.

function Car(manufacturer, model, year, color) {
return {
toString() {
return `${manufacturer} ${model} (${year}, ${color})`

const car = new Car('Aston Martin', 'V8 Vantage', '2012', 'Quantum Silver')

Expand snippet
Functional Programming
The function inner closes over fn and args in the following code.

function curry(fn) {
const args = []
return function inner(arg) {
if(args.length === fn.length) return fn(...args)
return inner

function add(a, b) {
return a + b

const curriedAdd = curry(add)
console.log(curriedAdd(2)(3)()) // 5

Expand snippet

Event-Oriented Programming
In the following code, function onClick closes over variable BACKGROUND_COLOR.

const $ = document.querySelector.bind(document)
const BACKGROUND_COLOR = 'rgba(200, 200, 242, 1)'

function onClick() {
$('body').style.background = BACKGROUND_COLOR

$('button').addEventListener('click', onClick)
<button>Set background color</button>

Expand snippet
In the following example, all the implementation details are hidden inside an immediately executed function expression. The functions tick and toString close over the private state and functions they need to complete their work. Closures have enabled us to modularize and encapsulate our code.

let namespace = {};

(function foo(n) {
let numbers = []

function format(n) {
return Math.trunc(n)

function tick() {
numbers.push(Math.random() * 100)

function toString() {

n.counter = {

const counter = namespace.counter

Expand snippet
Example 1
This example shows that the local variables are not copied in the closure: the closure maintains a reference to the original variables themselves. It is as though the stack frame stays alive in memory even after the outer function exits.

function foo() {
let x = 42
let inner = () => console.log(x)
x = x + 1
return inner

foo()() // logs 43

Expand snippet
Example 2
In the following code, three methods log, increment, and update, all close over the same lexical environment.

And every time createObject is called, a new execution context (stack frame) is created, and a completely new variable, x, and a new set of functions (log, etc.) are made that close over this new variable.

function createObject() {
let x = 42;
return {
log() { console.log(x) },
increment() { x++ },
update(value) { x = value }

const o = createObject()
o.log() // 43
o.log() // 5
const p = createObject()
p.log() // 42

Expand snippet
Example 3
If you are using variables declared using var, be careful you understand which variable you are closing over. Variables said using var are hoisted. This is much less of a problem in modern JavaScript due to the introduction of let and const.

In the following code, a new function inner is created each time around the loop, which closes over i. But because var i is hoisted outside the circle, all of these internal functions close over the same variable, meaning that the final value of i (3) is printed three times.

function foo() {
var result = []
for (var i = 0; i < 3; i++) {
result.push(function inner() { console.log(i) } )

return result

const result = foo()
// The following will print `3`, three times...
for (var i = 0; i < 3; i++) {

Final points:

  • Whenever a function is declared in JavaScript, closure is created.
  • Returning a function from inside another part is the classic example of closure because the state inside the outer function is implicitly available to the returned inner function, even after the external process has completed execution.
  • A closure is used whenever you use eval() inside a function. The text you eval can reference local variables of the process, and in the non-strict mode, you can create new local variables by using eval(‘var foo = …’).
  • When you use a new Function(…) (the Function constructor) inside a function, it does not close over its lexical environment: it closes over the global context instead. The new process cannot reference the local variables of the outer part.
  • A closure in JavaScript is like keeping a reference (NOT a copy) to the scope at the point of function declaration, which in turn keeps a relation to its outer area, and so on, all the way to the global object at the top of the scope chain.
  • A closure is created when a function is declared; this closure is used to configure the execution context when the process is invoked.
  • A new set of local variables is created every time a function is called.
How do JavaScript closures work?

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top