JavaScript Closures Practice Questions with Solutions

Introductions

A closure is created when a function remembers and can access variables from its outer scope, even after the outer function has finished running. Closures are an important JavaScript concept and are commonly used for private data, counters, function factories, and maintaining state. The examples below start with simple closures and gradually move toward practical use cases. JavaScript Closures practice questions with solutions help to understand the concepts.

Question 1: Create a Simple Closure

Problem

Create an outer function with a variable and return an inner function that can access that variable.

Solution

function outerFunction() {
    let message = "Hello JavaScript";

    function innerFunction() {
        console.log(message);
    }

    return innerFunction;
}

const result = outerFunction();

result();

Output

Hello JavaScript

Step-by-step Explanation

  1. outerFunction() creates a variable called message.
  2. innerFunction() is created inside outerFunction().
  3. The inner function can access message.
  4. outerFunction() returns innerFunction.
  5. The returned function is stored in result.
  6. result() runs the inner function.
  7. The inner function still remembers message.

This ability to remember variables from an outer scope is called a closure.


Question 2: Create a Counter Using a Closure

Problem

Create a function that returns another function. Each time the returned function is called, increase a counter by 1.

Solution

function createCounter() {
    let count = 0;

    return function() {
        count++;
        console.log(count);
    };
}

const counter = createCounter();

counter();
counter();
counter();

Output

1
2
3

Step-by-step Explanation

  1. createCounter() creates count with a value of 0.
  2. The inner function has access to count.
  3. createCounter() returns the inner function.
  4. counter stores that returned function.
  5. The first call changes count from 0 to 1.
  6. The second call changes it to 2.
  7. The third call changes it to 3.
  8. The value is remembered between function calls.

Question 3: Create a Private Variable

Problem

Create a function where the balance variable cannot be accessed directly from outside, but can be changed through a returned function.

Solution

function createAccount() {
    let balance = 1000;

    return function() {
        balance += 500;
        console.log("Balance:", balance);
    };
}

const account = createAccount();

account();
account();

Output

Balance: 1500
Balance: 2000

Step-by-step Explanation

  1. balance is created inside createAccount().
  2. It is not directly available outside the function.
  3. The returned function can access balance.
  4. Each time account() is called, 500 is added.
  5. The closure remembers the current balance.
  6. This creates a simple example of maintaining private data.

Question 4: Create a Greeting Function Factory

Problem

Create a function called createGreeting() that accepts a name and returns a function that displays a greeting for that name.

Solution

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

const greetRahul = createGreeting("Rahul");
const greetPriya = createGreeting("Priya");

greetRahul();
greetPriya();

Output

Hello, Rahul
Hello, Priya

Step-by-step Explanation

  1. createGreeting() receives a name.
  2. The inner function uses that name.
  3. createGreeting("Rahul") creates a function remembering "Rahul".
  4. createGreeting("Priya") creates another function remembering "Priya".
  5. Each function remembers its own value.
  6. This is an example of a function factory using closures.

Question 5: Create a Counter with Increment and Decrement

Problem

Create a counter that provides separate functions for increasing and decreasing a private count.

Solution

function createCounter() {
    let count = 0;

    return {
        increment: function() {
            count++;
            console.log("Count:", count);
        },

        decrement: function() {
            count--;
            console.log("Count:", count);
        }
    };
}

const counter = createCounter();

counter.increment();
counter.increment();
counter.decrement();

Output

Count: 1
Count: 2
Count: 1

Step-by-step Explanation

  1. count is created inside createCounter().
  2. The returned object contains two functions.
  3. Both functions can access count.
  4. increment() increases the value.
  5. decrement() decreases the value.
  6. The count variable remains private.
  7. Both functions share the same closure.

Question 6: Create a Discount Calculator with Closure

Problem

Create a function that accepts a discount percentage and returns another function that calculates the discounted price.

Solution

function createDiscount(discount) {
    return function(price) {
        return price - (price * discount / 100);
    };
}

const tenPercentOff = createDiscount(10);

console.log(tenPercentOff(1000));
console.log(tenPercentOff(500));

Output

900
450

Step-by-step Explanation

  1. createDiscount() receives the discount percentage.
  2. The inner function receives a product price.
  3. The inner function remembers the discount value.
  4. tenPercentOff remembers a 10% discount.
  5. For 1000, the discount is 100.
  6. The final price is 900.
  7. For 500, the discount is 50.
  8. The final price is 450.

Question 7: Create a Private User Name

Problem

Create a function that stores a user’s name privately and provides a function to display it.

Solution

function createUser(name) {
    return {
        getName: function() {
            return name;
        }
    };
}

const user = createUser("Aman");

console.log(user.getName());

Output

Aman

Step-by-step Explanation

  1. name exists inside createUser().
  2. The returned object contains getName().
  3. getName() can access the outer name variable.
  4. The outside code cannot directly access the local name variable.
  5. The function provides controlled access to the value.

This is one practical use of closures for creating private data.


Question 8: Create Multiple Independent Counters

Problem

Create two counters using the same function. Make sure each counter maintains its own value.

Solution

function createCounter() {
    let count = 0;

    return function() {
        count++;
        console.log(count);
    };
}

const counter1 = createCounter();
const counter2 = createCounter();

counter1();
counter1();

counter2();

counter1();
counter2();

Output

1
2
1
3
2

Step-by-step Explanation

counter1 and counter2 are created by separate calls to createCounter().

The first counter has its own count:

counter1 → 1 → 2 → 3

The second counter has its own count:

counter2 → 1 → 2

They do not share the same variable.

This happens because every call to createCounter() creates a separate closure.


Question 9: Use a Closure with setTimeout()

Problem

Create a function that remembers a message and displays it after a short delay.

Solution

function showMessage(message) {
    setTimeout(function() {
        console.log(message);
    }, 1000);
}

showMessage("Hello after one second");

Output

After approximately one second:

Hello after one second

Step-by-step Explanation

  1. showMessage() receives a message.
  2. setTimeout() receives an inner function.
  3. The inner function uses the message variable.
  4. JavaScript schedules the callback to run later.
  5. Even after showMessage() finishes, the callback remembers message.
  6. After approximately one second, the message is displayed.

This is a practical example of closures in asynchronous JavaScript.


Question 10: Create a Secure PIN Checker

Problem

Create a function that stores a PIN privately and returns another function that checks whether a supplied PIN is correct.

Solution

function createPinChecker(correctPin) {
    return function(pin) {
        if (pin === correctPin) {
            return "PIN is correct";
        }

        return "Incorrect PIN";
    };
}

const checkPin = createPinChecker(1234);

console.log(checkPin(1234));
console.log(checkPin(1111));

Output

PIN is correct
Incorrect PIN

Step-by-step Explanation

  1. createPinChecker() receives the correct PIN.
  2. The PIN is stored inside the outer function.
  3. The returned function can access the PIN.
  4. checkPin(1234) compares the supplied PIN with the remembered PIN.
  5. The first PIN matches.
  6. checkPin(1111) does not match.
  7. The original PIN is not directly exposed outside the closure.

This demonstrates how closures can help maintain private state.

Key Takeaways

  • A closure allows an inner function to remember variables from its outer scope.
  • Closures are created when functions are defined inside other functions and retain access to the outer variables.
  • Closures can maintain state between function calls.
  • Counters are a common example of closures.
  • Closures can be used to create private variables.
  • Function factories often use closures.
  • Different closures can maintain separate copies of data.
  • Closures are useful with asynchronous functions such as setTimeout().
  • Closures are an important concept behind many JavaScript patterns.
  • Understanding closures makes advanced JavaScript easier to learn.

FAQs

1. What is a closure in JavaScript?

A closure is a function that remembers variables from its surrounding lexical scope, even when the outer function has finished executing.

Example:

function outer() {
    let message = "Hello";

    return function() {
        console.log(message);
    };
}

const result = outer();

result();

2. Why are closures useful?

Closures are useful for:

  • Maintaining state
  • Creating private data
  • Creating function factories
  • Callbacks
  • Timers
  • Event handlers
  • Creating reusable functions

3. Can a closure remember a variable after a function finishes?

Yes. This is one of the main features of closures.

function createCounter() {
    let count = 0;

    return function() {
        count++;
        return count;
    };
}

The returned function continues to access count.

4. Are closures only used for counters?

No. Counters are just an easy way to understand them. Closures can also be used for private data, configuration functions, callbacks, timers, and many other JavaScript patterns.

5. Can two closures have separate values?

Yes.

const counter1 = createCounter();
const counter2 = createCounter();

Each call creates a separate closure with its own state.

6. Can closures be used with asynchronous JavaScript?

Yes. Closures are commonly used with callbacks such as setTimeout().

function greet(name) {
    setTimeout(function() {
        console.log("Hello " + name);
    }, 1000);
}

greet("Rahul");

The callback remembers the name variable.

7. What is a private variable using a closure?

A private variable is a variable that cannot be directly accessed from outside the function that created it, but an inner function can still access it.

function createUser() {
    let name = "Rahul";

    return function() {
        return name;
    };
}

Here, name is protected inside the closure.

Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.

Scroll to Top