

Have you ever wondered why some JavaScript functions seem to "remember" variables long after the function that created them has finished executing? This powerful capability is made possible by closure - a core concept in JavaScript that's often misunderstood.
Imagine a function carrying a backpack. When a function is created, it packs all the variables from its surrounding scope into this invisible backpack, which it carries along wherever it goes. This backpack is what makes closures so powerful - it allows functions to retain access to their lexical environment even after the original scope is gone, enabling you to write more modular and maintainable code.
A closure is incredibly useful for creating flexible and reusable code, but it can often be confusing when you're first learning JavaScript. This article aims to make closure less mysterious by providing practical examples on how closures work "under the hood," and insights into why they are so valuable in JavaScript development.
A closure is a function that "remembers" the variables from the context in which it was defined. This behavior is facilitated by JavaScript's internal mechanism, which allows functions to retain a reference to their lexical scope through an internal property like [[Environment]].
Closures are useful for:
Lexical scoping determines which variables are accessible in your code based on where they are written. In other words, the structure of the code - where you place your functions and variables - defines what is accessible and what isn’t. This is why variables declared outside a function can still be accessed inside that function if they are in the function's parent scope.
Think of it like nesting boxes - each box (scope) can access the things in the boxes outside it (its parent scopes).

In this example, the addItem function has access to the itemCount variable even though itemCount is defined outside of it, inside inventoryManager. This is possible because of the closure. The addItem function retains a reference to the itemCount variable from its parent scope (inventoryManager), allowing it to increment and use itemCount each time it is called.
Closures let functions "remember" the environment where they were created. When a function is defined, it keeps a reference to its outer lexical environment, which includes variables in scope at that time. Even after the outer function finishes executing, the inner function still has access to those variables.
Think of closures like a function carrying a "backpack." This backpack contains all the variables from its parent scope, allowing the function to access them no matter where or when it runs.
To understand closures more deeply, let’s explore how JavaScript handles function execution.
Every time a function is called, the JavaScript engine creates a new execution context, which includes:
Closures are often used to create function factories - functions that generate other functions customized with specific variables. This is a powerful pattern when you need to create functions that share some similar behavior but differ based on specific values.

In this example, createDiscount returns a new function that calculates the price after applying a specific discount rate. The returned function retains access to the discountRate variable through a closure. This allows you to create multiple discount functions (tenPercentOff, twentyPercentOff) with different values, without redefining the core logic each time.
Closures allow us to create private variables, making it easy to encapsulate data so that it cannot be accessed or modified directly from outside the function.

In this example, count is not directly accessible from outside the createCounter function. The returned function has access to count through a closure, allowing it to increment and log the count each time it is called. This means the variable count is effectively private, ensuring it cannot be accidentally modified from outside the createCounter function.
Closures are particularly useful in asynchronous programming, such as when working with timers or event handlers. They allow us to retain access to their original scope, even after some time has passed.

In this example, the createReminder function returns another function that uses setTimeout to display a reminder message after a specified number of seconds. The returned function retains access to the seconds variable through a closure, allowing it to use the correct delay each time it's called, even though createReminder has already finished executing. This is a powerful demonstration of how closures help maintain state in asynchronous situations.
To get an even clearer picture of how closures work, it helps to visualize their scope chain.
Global Scope
└── outerFunction Scope
└── innerFunction Scope
Each inner scope has access to its own variables and those of its parent scopes, forming a chain that the JavaScript engine traverses when resolving variable names.
Closures are one of the core features that make JavaScript such a powerful and flexible language. They allow functions to "remember" the environment they were created in - letting us retain private variables, create specialized behaviors with function factories, and manage state effectively.
If you're ready to deepen your understanding of closures, there’s no substitute for hands-on practice. CSX, Codesmith's free learning platform, offers an excellent set of interactive challenges. You can explore the CSX Closures Unit to gain practical experience and enhance your intuition about how closures work.
By experimenting with function factories, maintaining private states, and handling asynchronous operations using closures, you will build the skills needed to write modular and maintainable code. While closures might seem challenging at first, with practice, they will become an essential part of your JavaScript toolkit.
.png)

Explore CS Prep further in our beginner-friendly program.
Get more free resources and access to coding events every 2 weeks.

Connect with one of our graduates/recruiters.

Our graduates/recruiters work at:

Connect with one of our recruiters to learn about their journeys.
Our graduates/recruiters work at: