JavaScript

JS Basics

JS Variables & Operators

JS Data Types & Conversion

JS Numbers & Math

JS Strings

JS Dates

JS Arrays

JS Control Flow

JS Loops & Iteration

JS Functions

JS Objects

JS Classes & Modules

JS Async Programming

JS Advanced

JS HTML DOM

JS BOM (Browser Object Model)

JS Web APIs

JS AJAX

JS JSON

JS Graphics & Charts

Function Closures


Closures are a fundamental concept in JavaScript that allow functions to access variables from an outer scope even after that outer function has finished executing. They are a powerful feature for creating private variables, maintaining state, and building modular and reusable code. Understanding closures is essential for advanced JavaScript programming, especially when dealing with callbacks, event handlers, asynchronous code, and functional programming patterns.

In this tutorial, you will learn what closures are, why they are important, how to use them, practical examples, common mistakes, best practices, and real-world applications.

Why Closures Are Important

Closures are important because they allow you to:

  • Preserve state between function calls

  • Create private variables that cannot be accessed directly from the outside

  • Implement modular and reusable code

  • Work with callbacks, asynchronous operations, and event handlers

  • Enable functional programming patterns such as currying and partial application

Without closures, managing state or encapsulating variables would require global variables or complex object-oriented patterns, which can lead to code that is harder to maintain and debug.

What is Closures

A closure is created whenever a function is defined inside another function, giving the inner function access to the outer function’s variables. This includes:

  • Parameters of the outer function

  • Local variables of the outer function

  • Variables in the scope chain above the outer function

Even after the outer function has finished executing, the inner function retains access to these variables. This ability to "remember" the environment is what makes closures powerful.

Syntax Example

function outerFunction(outerVariable) {
    return function innerFunction(innerVariable) {
        console.log("Outer: " + outerVariable);
        console.log("Inner: " + innerVariable);
    };
}

const newFunction = outerFunction("Aarushi");
newFunction("Patna");

Output:

Outer: Aarushi
Inner: Patna

Here, innerFunction has access to outerVariable even though outerFunction has already finished executing. This demonstrates how closures preserve access to the outer scope.

Closures with Private Variables

Closures are commonly used to create private variables that cannot be accessed directly:

function createCounter() {
    let count = 0;
    return function() {
        count++;
        console.log("Count: " + count);
    };
}

const counter = createCounter();
counter();
counter();
counter();

Output:

Count: 1
Count: 2
Count: 3

Here, the count variable is private. It is only accessible through the inner function, preventing external modification.

Closures in Event Handlers

Closures are often used in event handlers to maintain state:

function setupButton(buttonId, name) {
    let clicks = 0;
    document.getElementById(buttonId).addEventListener("click", function() {
        clicks++;
        console.log(name + " clicked " + clicks + " times");
    });
}

setupButton("btn1", "Isha");
setupButton("btn2", "Saanvi");

Each button maintains its own clicks count because each event handler forms a closure over its own clicks variable.

Closures with Currying and Partial Application

Closures can be used for currying, where a function is transformed into a sequence of functions each taking a single argument:

function multiply(a) {
    return function(b) {
        return a * b;
    };
}

const double = multiply(2);
console.log(double(5));
console.log(double(10));

Output:

10
20

The inner function remembers the a argument from the outer function, allowing you to create specialized functions like double.

Common Mistakes

  • Forgetting that closures maintain references to variables, which can lead to unintended memory usage

  • Overusing closures unnecessarily, which can make code harder to read

  • Assuming closures create a copy of the variable instead of maintaining a reference

  • Using closures inside loops without understanding variable scope, leading to unexpected behavior

Best Practices

  • Use closures to encapsulate private data and state

  • Avoid creating unnecessary closures in performance-critical code

  • Be aware of memory usage when closures capture large objects

  • Use meaningful variable names to clarify scope and intent

  • Combine closures with modular patterns to organize complex applications

Real-World Applications

Closures are widely used in:

  • Creating counters and private state variables

  • Event handlers and callback functions

  • Functional programming techniques such as currying and partial application

  • Encapsulation in JavaScript modules

  • Maintaining state in asynchronous operations such as timers, promises, and AJAX calls

Practical Examples

Example 1: Counter with Reset

function createCounter() {
    let count = 0;
    return {
        increment: function() {
            count++;
            console.log(count);
        },
        reset: function() {
            count = 0;
            console.log("Counter reset");
        }
    };
}

const counter = createCounter();
counter.increment();
counter.increment();
counter.reset();
counter.increment();

Output:

1
2
Counter reset
1

Example 2: Custom Greeting

function createGreeting(greeting) {
    return function(name) {
        console.log(greeting + ", " + name + "!");
    };
}

const sayHello = createGreeting("Hello");
const sayGoodMorning = createGreeting("Good morning");

sayHello("Aarushi");
sayGoodMorning("Isha");

Output:

Hello, Aarushi!
Good morning, Isha!

Example 3: Maintaining Private Scores

function createGame(name) {
    let score = 0;
    return function(points) {
        score += points;
        console.log(name + "'s score: " + score);
    };
}

const game1 = createGame("Saanvi");
game1(10);
game1(5);

const game2 = createGame("Priya");
game2(7);

Output:

Saanvi's score: 10
Saanvi's score: 15
Priya's score: 7

Summary of Function Closures

Closures are a core feature of JavaScript that allow functions to access variables from their outer scope even after the outer function has executed. They are invaluable for maintaining state, creating private variables, building modular and reusable code, and implementing advanced patterns like currying and partial application. Proper understanding and use of closures help you write clean, maintainable, and efficient JavaScript applications.


Practice Questions

Q1. Write a function createCounter() that returns another function which increases and returns a private counter each time it's called.

Q2. Create a function greet(message) that returns a function which accepts a name and logs message + name.

Q3. Create a function multiplier(factor) that returns a function to multiply any number by that factor.

Q4. Write a closure that stores a secret message and provides a method to read it but not modify it.

Q5. Create a once() function that allows the given function to run only once and ignores subsequent calls.

Q6. Write a closure that maintains a list and provides addItem() and getItems() methods.

Q7. Create a closure that tracks the number of times a button is clicked (simulate clicks using a function).

Q8. Build a function makeAdder(x) that returns another function which adds x to its argument.

Q9. Create a timer() closure that stores the start time and returns the elapsed time when called again.

Q10. Write a closure-based cache() function that stores and returns computed values based on input (e.g., square of number).


Try a Short Quiz.

No quizzes available.


JavaScript

JS Basics

JS Variables & Operators

JS Data Types & Conversion

JS Numbers & Math

JS Strings

JS Dates

JS Arrays

JS Control Flow

JS Loops & Iteration

JS Functions

JS Objects

JS Classes & Modules

JS Async Programming

JS Advanced

JS HTML DOM

JS BOM (Browser Object Model)

JS Web APIs

JS AJAX

JS JSON

JS Graphics & Charts

Go Back Top