Closures in JavaScript Explained Visually (Beginner’s Tutorial)

Visual Studio Code (VS Code)

Introduction

Had you ever asked this question about JavaScript: What is a closure? You are certainly not the only one. Closures are undoubtedly one of the greatest and most confusing concepts in JavaScript.

This tutorial on closures in JavaScript is all set to take you through this amazing concept in a simple manner with various explanations, illustrations, and examples. By the end of the content, you will know for sure what closures in JavaScript and would be able to understand when and how to use them.

What Is a Closure in JavaScript?

A closure is a function that has access to its outer function scope even after that outer function has returned. 

Let’s break that down:

  • A function is declared inside another function.
  • The inner function is able to access variables declared in the outer function-the outer function’s execution is done.
  • This persistent access is called closure.

Understanding Lexical Scope in JavaScript

It is important to comprehend lexical scope in JavaScript before continuing any further.

Lexical Scope Means:

In JavaScript, the variable scope is defined with respect to where the function and variable are defined in the source code.

This means:

  • An inner function can access the variables defined in its outer (parent) functions.
  • Such secure accessibility will be ensured during the time of writing the code (not at runtime).

Example:

function outer() {
  let name = “Alice”;
  function inner() {
    console.log(name);
  }
  inner(); // Output: Alice
}
outer();

Here, inner() is inside outer(), so it can access name because of lexical scoping.

JavaScript Closure Example (Step-by-Step)

Let’s go beyond and see a true closure in action — where a function returns another function.

function counter() {
  let count = 0;
  return function() {
    count++;
    console.log(count);
  };
}
const increment = counter();
increment(); // 1
increment(); // 2
increment(); // 3

Why is this a closure?

  • counter() finished executing. 
  • But the returned function does not forget the count variable.
  • This “memory” of count is called closure.

Visual Explanation

Let’s visualize it like this:
counter() –> creates count = 0
    |
    └── inner function remembers → count
         └── still accessible via increment()

Even if counter() was not present anymore, count lives on in the closure. This is what makes closure really powerful.

Real-World Uses of JavaScript Closures

Closures aren’t just theory—they solve practical problems:

1. Data Privacy (Private Variables)

function createSecret() {
  let secret = “Top Secret”;
  return {
    getSecret: () => secret
  };
}
const mySecret = createSecret();
console.log(mySecret.getSecret()); // Top Secret

Here, secret is protected. No one can access it directly—only via getSecret().

2. Function Factories

function multiplyBy(x) {
  return function(y) {
    return x * y;
  };
}
const double = multiplyBy(2);
console.log(double(5)); // 10

Closures allow double to remember the value 2 even after multiplyBy() is done.

3. Maintaining State in Async Code

function greet(name) {

  setTimeout(() => {
    console.log(`Hello, ${name}`);
  }, 1000);
}
greet(“Jane”);

Even after greet() ends, the setTimeout callback remembers the name variable thanks to the closure.

Common Pitfalls with Closures

Loop Variable Trap

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
// Output: 3, 3, 3

Fixed with let

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
// Output: 0, 1, 2

let creates block scope, so each loop iteration creates a new closure with its own i.

Best Practices for Using Closures

TipWhy It Matters
Avoid excessive nestingIt makes debugging hard
Use closures for encapsulationGreat for keeping data private
Be mindful of memory leaksDon’t hold onto large DOM elements
Use meaningful namesMakes closures easier to understand

Review: Closures at a Glance

  • Closures are used by inner functions to remember outer variables.
  • Based on lexical scope; that is, based on code structure.
  • Used for private data, custom functions and async callbacks.
  • Mastering them gives you more control over state, memory, and logic.

Try This Exercise

function createGreeting(name) {
  return function(message) {
    return `${message}, ${name}`;
  };
}
const greetJohn = createGreeting(“John”);
console.log(greetJohn(“Good morning”)); // Good morning, John

Can you explain why this works? (Hint: closure!)

Conclusion

Sure, closures in JavaScript may appear to be confusing at first perhaps only until one learns about lexical scope, and how functions remember their environments, when things fall into place. 

Whether you’re developing very advanced features, working with async tasks, or just encapsulating logic – closures are essential to writing clean, powerful JavaScript code.

Leave a Reply

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