Demystifying Closures in JavaScript: Understanding Memory Allocation and Lexical Scope

Pallavi Ganpat Babar
Women in Technology
4 min readJun 25, 2023

Are you curious to unravel the hidden potential of JavaScript? Have you ever heard the phrase “closures” and wondered what they are and why they are important? If so, you’ve come to the correct place.

In this article, we’ll look at the interesting realm of closures and their role in JavaScript programming.

Closures are more than simply a technical notion; they are a powerful tool that can help you build cleaner, more efficient, more flexible code.

Understanding closures and their inner workings will allow you to reach new heights in JavaScript development. Whether you’re a newbie just getting started with JavaScript or an experienced developer trying to improve your abilities, learning about closures is a must. So, let’s dive into this informative discussion of closures in JavaScript and see how they can change the way you write code. Get ready to unlock the potential of closures and witness the true artistry of JavaScript programming!

What is a Closure in JavaScript?

A closure in JavaScript is an inner function that has access to the global scope, its outer function’s scope, and its own scope. It means that even after the outer function has done running (its execution context has vanished), the inner function can still access its variables and parameters.

Let’s look at an example to better comprehend this concept:

function outerFunction() {
var outerVariable = 'I am from the outer function!';
let counter = 0;

function incrementCounter () {
counter++;
console.log(counter);
}

return incrementCounter;
}

var closureExample = outerFunction();
closureExample();

In this example, incrementCounter is nested ( is a closure ) within outerFunction. The variable outerVariable and counterare defined within outerFunction. When incrementCounter is invoked, it reads and reports the value of thecounter to increment and then logs it to the console.

Memory allocation in closures is an essential concept to understand. When an inner function references variables or parameters of its outer function, those variables and parameters are stored in memory. The memory allocation for closures works as follows:

  1. In Global Memory, the label outerFunction is defined, with an entire function as its value.
  2. The outerFunction is called, creating a new execution context. It defines the outerVariable , counterand the incrementCounter within its scope.
  3. While being returned, the incrementCounter carries its own BACKPACK (which we will see shortly) containing all of its referenced data.
  4. Now, in Global Memory, a new variable named closureExample is defined to hold the value returned by outerFunction, which is incrementCounter.
  5. Now, when we call closureExample, incrementCounter is what we are really calling.
  6. When the incrementCounter is invoked, it searches for the variable counterwithin its own scope. If it doesn't find it, it looks for it in the next outer scope, which is the scope of outerFunction. In this case, it finds outerVariable in the lexical scope of incrementCounter.
  7. The innerFunction then logs the value of counter to the console, displaying '1'.

Based on where variables are located in the source code, lexical scope dictates whether or not they are accessible. Because the counter in the previous example is lexically (statically) scoped within outerFunction, incrementCounter has access to it.

It’s important to remember that lexical scope is established during function definition, not execution. This means that even when closures are used outside of their intended scope, references to the variables they have captured remain intact. This concept is referred as Backpack.

Or Closed Over Variable Environment (COVE) or Persistent Lexical Scope Referenced Data (PSRD), which are the terms used in the industry.

function outerFunction() {
var outerVariable = 'I am from the outer function!';
let counter = 0;

function incrementCounter () {
counter++;
console.log(counter);
}

return incrementCounter;
}

For above function only the counter will be present in the Backpack or Persistent Lexical Scope Referenced Data (PSRD) of incrementCounter, not the outerVariable. This is because the counter variable is used within the incrementCounter function. This function does not wish to carry outerVariable since it will cause a memory leak. Here counter is a private variable that can only be accessed through the incrementCounter function.

Closures can be used in a wide variety of real-world JavaScript programming scenarios. Here are some of the most prevalent use cases for closures:

1. Data Privacy and Encapsulation:

Closures provide a mechanism for creating private variables and functions. You can manage access to variables and prevent undesired changes from outside the closure by encapsulating data within a closure. This feature is particularly useful and very handy when creating modules or libraries when you only want to expose specific functions or variables while hiding others.

2. Callbacks and Event Handling:

When dealing with asynchronous operations, such as managing callbacks or event listeners, closures are extensively used. Closures allow you to maintain the context and state of a function even after it has been passed as a callback. This ensures that when the callback is executed, the function has access to the variables and parameters it need. It’s an effective method for handling asynchronous flows while ensuring data integrity.

3. Memoization and Caching:

Closures can be used to improve memoization and caching. Memoization involves caching the results of expensive function calls and returning the cached value when the same inputs are encountered again. By utilising closures to store the cached results, you can create memoized functions that significantly improve performance in scenarios where the same computations are repeated with identical inputs.

These are just a few examples of how closures can be used in JavaScript. Understanding closures and their potential applications enables you to write code that is more expressive, modular, and efficient. You can improve your JavaScript skills by introducing closures into your programming arsenal.

Now armed with a deep understanding of closures, it’s time to unlock the full potential of JavaScript and bring your projects to new heights.

Embrace the power of closures, harness the artistry of JavaScript programming, and let your imagination soar.

Happy coding with closures in JavaScript!

--

--

Pallavi Ganpat Babar
Women in Technology

Pallavi is a software developer and writer, passionate about exploring the latest tech trends. Follow for insights on software development, tech and more.