codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🌐

JavaScript

19 / 65 topics
14JavaScript Functions15JavaScript Function Expressions16JavaScript Arrow Functions17JavaScript Variable Scope18JavaScript Hoisting19JavaScript Closures20JavaScript Recursion
Tutorials/JavaScript/JavaScript Closures
🌐JavaScript

JavaScript Closures

Updated 2026-05-12
30 min read

JavaScript Closures

In the world of programming, especially in languages like JavaScript that support first-class functions and higher-order functions, closures play a crucial role. A closure is a function that retains access to its lexical scope even when executed outside that scope. This concept is fundamental to understanding advanced JavaScript features such as callbacks, event handlers, and modules.

Introduction

Closures are one of the powerful yet often misunderstood features of JavaScript. They allow functions to "remember" the environment in which they were created, enabling them to access variables from their parent scope even after that scope has finished executing. Understanding closures is essential for writing clean, maintainable, and efficient code.

In this tutorial, we will explore what closures are, how they work, and why they matter in JavaScript programming. We'll go through several examples to solidify your understanding and see how closures can be used in practical scenarios.

Core Content

What is a Closure?

A closure is formed when a function captures its lexical environment (the set of variables that are in scope at the time of the function's creation) and retains access to it even after the function has finished executing. This means that the function can still "remember" and access those variables, even if they are no longer accessible in the usual way.

How Closures Work

To understand closures better, let's break down how they work:

  1. Lexical Scope: When a function is defined, it captures its lexical scope, which includes all the variables that are in scope at the time of its creation.
  2. Function Execution Context: When a function is executed, it has its own execution context, including its local variables and parameters.
  3. Closure Formation: If a function references variables from its outer (lexical) scope, those variables become part of the closure. The function retains access to these variables even after the outer function has finished executing.

Example 1: Basic Closure

Let's start with a simple example to illustrate how closures work:

closure-basic.js
1function createCounter() {
2 let count = 0;
3 return function() {
4 count++;
5 return count;
6 };
7}
8
9const counter = createCounter();
10console.log(counter()); // Output: 1
11console.log(counter()); // Output: 2
12console.log(counter()); // Output: 3
Output
1
2
3

In this example, createCounter is a function that returns another function. The returned function has access to the count variable from its parent scope (createCounter). Even though createCounter has finished executing and its execution context has been destroyed, the returned function still retains access to count, forming a closure.

Example 2: Closure with Parameters

Closures can also capture parameters:

closure-parameters.js
1function createMultiplier(multiplier) {
2 return function(number) {
3 return number * multiplier;
4 };
5}
6
7const double = createMultiplier(2);
8console.log(double(5)); // Output: 10
9
10const triple = createMultiplier(3);
11console.log(triple(4)); // Output: 12
Output
10
12

Here, createMultiplier takes a parameter multiplier and returns a function that multiplies a given number by multiplier. The returned function retains access to the multiplier variable, forming a closure.

Example 3: Common Mistakes

While closures are powerful, they can also lead to common mistakes if not used carefully:

  1. Memory Leaks: If a closure captures variables that are no longer needed, it can cause memory leaks.
  2. Unexpected Behavior: Misunderstanding how closures work can lead to unexpected behavior in your code.
closure-mistakes.js
1function createGreeting(name) {
2 let greeting = 'Hello, ' + name;
3 return function() {
4 console.log(greeting);
5 };
6}
7
8const greetJohn = createGreeting('John');
9greetJohn(); // Output: Hello, John
10
11// Changing the outer variable
12name = 'Jane';
13greetJohn(); // Output: Hello, Jane (unexpected behavior)
Output
Hello, John
Hello, Jane

In this example, changing the name variable outside the closure affects the output of the closure. This can be confusing and should be avoided.

Practical Example

Now that we've covered the basics of closures, let's look at a more practical example. Suppose you want to create a module that keeps track of user sessions:

closure-module.js
1function createUserSession() {
2 let sessionCount = 0;
3 return {
4 login: function() {
5 sessionCount++;
6 console.log('User logged in. Total sessions:', sessionCount);
7 },
8 logout: function() {
9 if (sessionCount > 0) {
10 sessionCount--;
11 console.log('User logged out. Remaining sessions:', sessionCount);
12 } else {
13 console.log('No active sessions.');
14 }
15 }
16 };
17}
18
19const userSession = createUserSession();
20userSession.login(); // Output: User logged in. Total sessions: 1
21userSession.logout(); // Output: User logged out. Remaining sessions: 0
Output
User logged in. Total sessions: 1
User logged out. Remaining sessions: 0

In this example, createUserSession returns an object with two methods: login and logout. Both methods have access to the sessionCount variable, forming a closure. This allows the module to maintain state across multiple method calls.

Summary

  • Closures are functions that retain access to their lexical scope even when executed outside it.
  • They allow functions to "remember" variables from their parent scope.
  • Closures are formed when a function captures its lexical environment and retains access to it.
  • Understanding closures is essential for advanced JavaScript programming, including callbacks, event handlers, and modules.
Key ConceptDescription
Lexical ScopeThe set of variables that are in scope at the time of the function's creation.
Execution ContextThe environment in which a function is executed, including its local variables and parameters.
Closure FormationWhen a function references variables from its outer scope, those variables become part of the closure.

What's Next?

Now that you have a solid understanding of closures, it's time to explore another fundamental JavaScript concept: recursion. Recursion is the process where a function calls itself in order to solve a problem. It's a powerful tool for solving complex problems and is widely used in algorithms and data structures.

In the next tutorial, we will dive into recursion, learn how to write recursive functions, and understand their advantages and limitations. Stay tuned!


PreviousJavaScript HoistingNext JavaScript Recursion

Recommended Gear

JavaScript HoistingJavaScript Recursion