Understanding
Closures in JavaScript



What are Closures in JavaScript?

In JavaScript, a closure is formed when an inner function has access to variables from an outer function’s scope, even after the outer function has returned. This is possible because functions in JavaScript form lexical environments at the time of their definition.

Why Closures Are Important?

Example 1: Basic Closure

Let’s start with a simple example to see how closures retain access to outer function variables.


function outer() {
  let name = "JavaScript";
  function inner() {
    console.log("Hello from " + name);
  }
  return inner;
}

const greet = outer();
greet(); // calling inner function
    

Output:

Hello from JavaScript

Explanation:

When outer() is called, it returns the inner function. Even though outer() has finished executing, the returned inner function still "remembers" the variable name from its lexical scope. This is closure in action.

Question:

Why does the inner function still have access to name after outer() returns?

Answer: Because the inner function forms a closure and "closes over" the variable name. JavaScript's function scope retains access to variables from the context in which the function was defined.

Example 2: Closures to Create Private Variables

Closures are often used to create data that cannot be directly accessed from the outside.


function createCounter() {
  let count = 0;
  return function() {
    count++;
    console.log("Count is", count);
  }
}

const counter1 = createCounter();
counter1(); // Count is 1
counter1(); // Count is 2
    

Output:

Count is 1
Count is 2

Explanation:

The variable count is not accessible from outside createCounter(). But the returned function can access and modify it. This is a powerful technique for data privacy.

Question:

What happens if we create another counter?


const counter2 = createCounter();
counter2(); // Count is 1
    

Output:

Count is 1

Each call to createCounter() returns a new closure with its own private count.

Example 3: Closures Inside Loops (Common Interview Trap)

Let’s look at how closures behave inside loops and how to avoid common pitfalls.


// Common mistake
for (var i = 1; i <= 3; i++) {
  setTimeout(function() {
    console.log("i:", i);
  }, i * 1000);
}
    

Output:

i: 4
i: 4
i: 4

Why 4?

The setTimeout callback forms a closure over the i variable, which after the loop ends is 4. All three closures reference the same i.

Fix using IIFE:


for (var i = 1; i <= 3; i++) {
  (function(j) {
    setTimeout(function() {
      console.log("i:", j);
    }, j * 1000);
  })(i);
}
    

Output:

i: 1
i: 2
i: 3

Fix using let:


for (let i = 1; i <= 3; i++) {
  setTimeout(function() {
    console.log("i:", i);
  }, i * 1000);
}
    

Using let ensures that each iteration of the loop has its own separate block scope for i.

Key Points to Remember

Practice Questions

  1. What will be logged to the console in each closure example above?
  2. How can you use closures to implement private methods?
  3. Can closures be garbage collected? Under what conditions?


Welcome to ProgramGuru

Sign up to start your journey with us

Support ProgramGuru.org

You can support this website with a contribution of your choice.

When making a contribution, mention your name, and programguru.org in the message. Your name shall be displayed in the sponsors list.

PayPal

UPI

PhonePe QR

MALLIKARJUNA M