Back to Roadmap
6:00

Closures in JavaScript

Understand how closures work in JavaScript and how they enable powerful patterns like data encapsulation and function factories

6 MIN READ VERIFIED CURRICULUM

A closure in JavaScript is created when a function remembers and accesses variables from its outer (lexical) scope, even after that outer function has finished executing.

Closures are one of the most powerful and important concepts in JavaScript, enabling data privacy, function factories, and advanced functional programming patterns.

What is a Closure?

A closure is the combination of a function and the lexical environment in which it was declared.

It allows inner functions to access variables defined in their outer function scope even after the outer function has returned.

Basic Example of Closure

In this example, the inner function remembers the variable from its outer function.

function outer() {
  let count = 0;

  function inner() {
    count++;
    console.log(count);
  }

  return inner;
}

const counter = outer();
counter();
counter();
javascript

Even though outer() has finished execution, the inner function still has access to the variable count.

How Closures Work Internally

Closures work because JavaScript uses lexical scoping, meaning functions are executed using the scope in which they were defined.

When a function is returned, it retains a reference to its outer scope variables.

Lexical Scope and Closures

Lexical scope means a function can access variables from its parent scope at the time of definition.

Closures extend this concept by preserving access even after the parent function execution is complete.

function greet() {
  let name = 'John';

  return function () {
    console.log('Hello ' + name);
  };
}

const sayHello = greet();
sayHello();
javascript

Practical Use: Data Encapsulation

Closures are often used to create private variables that cannot be accessed directly from outside the function.

This helps in achieving data encapsulation in JavaScript.

function createBankAccount() {
  let balance = 0;

  return {
    deposit(amount) {
      balance += amount;
    },
    getBalance() {
      return balance;
    }
  };
}

const account = createBankAccount();
account.deposit(100);
console.log(account.getBalance());
javascript

Function Factories

Closures allow us to create function factories that generate specialized functions dynamically.

Each generated function retains its own independent lexical environment.

function multiply(x) {
  return function (y) {
    return x * y;
  };
}

const double = multiply(2);
console.log(double(5));
javascript

Common Mistakes with Closures

A common mistake is assuming the value is copied instead of referenced inside a closure.

This often causes unexpected results in loops using var instead of let.

for (var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i);
  }, 100);
}
javascript

This prints 3 three times because var is function-scoped, not block-scoped.

Fixing Closure Issues with let

Using let instead of var creates a new block scope for each iteration.

for (let i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i);
  }, 100);
}
javascript

Real-World Usage

Closures are widely used in event handlers, React hooks, memoization, and module patterns.

They are essential in modern JavaScript frameworks and libraries.

Best Practices

Use closures intentionally for encapsulation rather than accidentally creating memory leaks.

Be mindful of retained references in long-running applications.

Summary

Closures allow functions to retain access to their lexical scope even after execution.

Mastering closures is essential for advanced JavaScript development and understanding frameworks like React.