DEV Community

Marcos Schead
Marcos Schead

Posted on

Understanding Closures in JavaScript: A Deep Dive

Closures are a fundamental concept in JavaScript, often considered a cornerstone of understanding how the language handles functions and scope. In this blog post, we'll explore the concept of closures step by step, using an example to illustrate how closures work in practice.

Step-by-Step Breakdown

Step 1: Define the Parent Function

First, we define a function named parent. Inside this function, a variable num is declared and initialized to 0.

function parent() {
  let num = 0;
}
Enter fullscreen mode Exit fullscreen mode

This variable num is scoped to the parent function, meaning it cannot be accessed from outside the parent function.

Step 2: Define the Child Function

Next, within the parent function, we define another function named child.

function parent() {
  let num = 0;

  function child() {
    num += 1;
    console.log(num);
  }
}
Enter fullscreen mode Exit fullscreen mode

The child function increments the num variable by 1 and logs its value to the console. The child function has access to the num variable because it is defined within the scope of the parent function.

Step 3: Return the Child Function

The parent function returns the child function. This is crucial because it means that when parent is called, it returns the child function, which retains access to the num variable even after parent has finished executing.

function parent() {
  let num = 0;

  function child() {
    num += 1;
    console.log(num);
  }

  return child;
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Create an Incrementer

Here, we call the parent function and store the returned child function in the incrementer variable.

const incrementer = parent();
Enter fullscreen mode Exit fullscreen mode

At this point, incrementer is a function that can increment and log the num variable.

Step 5: Execute the Incrementer Function

We call the incrementer function twice. Each time it is called, the num variable is incremented by 1 and its value is logged to the console.

incrementer(); // Output: 1
incrementer(); // Output: 2
Enter fullscreen mode Exit fullscreen mode

The output is 1 on the first call and 2 on the second call. This demonstrates that the num variable retains its state between function calls.

What is a Closure?

Closure in the Code Context

In the context of the code provided, a closure is created when the child function is defined within the parent function and returned. The child function retains access to the num variable defined in the parent function even after the parent function has finished executing. This retained access allows the child function to modify and log the num variable each time it is called.

Closure in General JavaScript Context

In a broader sense, a closure in JavaScript is when an inner function has access to variables in its outer enclosing function, even after the outer function has finished executing. This includes access to:

  • Its own scope (variables defined between its curly braces)

  • The scope of the outer function

  • The global scope

Closures enable powerful programming patterns such as data encapsulation, partial application, and function factories. They allow for the creation of private variables and functions, which can only be accessed and modified through the closure, promoting a cleaner and more modular code structure.

Conclusion

Closures are a powerful and essential feature of JavaScript, enabling functions to retain access to their lexical scope even when executed outside that scope. By understanding and utilizing closures, developers can create more modular, maintainable, and flexible code. The example provided demonstrates how closures work in practice, showing step-by-step how a function can retain access to variables defined in its parent scope.

Mastering closures is crucial for advanced JavaScript programming techniques, enabling you to write more robust and encapsulated code. Embracing closures can significantly enhance your ability to solve complex problems and create sophisticated applications.

Top comments (4)

Collapse
 
i-sultan0 profile image
Sultan Akhter

After reading this, I don't think someone can explained the 'Closures' in that much simplistic and detailed way. Hats off to you for explaining this concept so well.
I also wrote an article about closures few days back, but your explanation is more detailed than mine
.

Collapse
 
schead profile image
Marcos Schead

Thank you so much, my friend!

I've been familiar with the concept of closures for years, but I've often struggled to explain it to other developers. I'm pleased to know that I was able to achieve my goal.

That gives me more motivation for my upcoming posts :)

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

This post isn't quite accurate. Nesting of functions is not required to create closures. All that is required is creating a function. ALL functions have an associated closure.

What you've written about is one particular way (probably the most common) we can make use of closures.

Collapse
 
jangelodev profile image
João Angelo

Hi Marcos Schead,
Top, very nice and helpful !
Thanks for sharing.