Skip to content

JavaScript Closure & Function Interview Questions (With Answers)

Closures are one of the most asked topics in JavaScript interviews. Almost every interviewer has a favourite closure question, and most of them are output-based.

Before you start, make sure you’ve read the Functions, Higher Order Functions and Closures articles. As always, try to work out each answer yourself before reading the explanation.

function createCounter() {
    let count = 0;

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

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2

In the above example, you can see that:

  1. createCounter runs and finishes, so you’d expect count to be thrown away.
  2. But the inner function still uses count, so JavaScript keeps it alive.
  3. Every time we call counter(), it updates that same count.

A closure is a function that keeps access to the variables from the place where it was written, even after that outer function has finished running.

2. Do two closures from the same function share variables?

Section titled “2. Do two closures from the same function share variables?”
function createCounter() {
    let count = 0;
    return function () {
        count++;
        return count;
    };
}

const counterA = createCounter();
const counterB = createCounter();

console.log(counterA());
console.log(counterA());
console.log(counterB());

Answer: 1, 2, 1

In the above example, you can see that:

  1. Every call to createCounter() creates a brand-new count starting at 0.
  2. counterA and counterB each remember their own count.
  3. So calling counterA twice doesn’t affect counterB. It still starts from 1.

Remember the car factory from the Closures article? Every car gets its own odometer.

3. Does a closure remember the value or the variable?

Section titled “3. Does a closure remember the value or the variable?”
function outer() {
    let message = "Hello";

    const sayIt = function () {
        console.log(message);
    };

    message = "Bye";
    return sayIt;
}

const fn = outer();
fn();

Answer: Bye

Hmm, you may be wondering why it isn’t Hello, since message was "Hello" when sayIt was created.

In the above example, you can see that:

  1. A closure doesn’t take a snapshot of the value. It keeps a link to the variable itself.
  2. By the time sayIt actually runs, message has already been changed to "Bye".
  3. So it prints whatever is inside the variable at the moment it runs.

4. Why does var in a for loop with setTimeout print the same number?

Section titled “4. Why does var in a for loop with setTimeout print the same number?”
for (var i = 1; i <= 3; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1000);
}

Answer: 4, 4, 4

Wait, what? Shouldn’t it be 1, 2, 3?

In the above example, you can see that:

  1. setTimeout doesn’t run its callback right away. The loop finishes first, and the callbacks run later.
  2. var is function-scoped, not block-scoped. So there’s only one i shared by the whole loop.
  3. The loop keeps going until i becomes 4, and then it stops.
  4. A second later, all three callbacks run. They all point to that same i, which is now 4.

Now the fix. Just change var to let:

for (let i = 1; i <= 3; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1000);
}
// 1, 2, 3

let is block-scoped, so JavaScript creates a new i for every round of the loop. Each callback closes over its own i.

5. Can you call a function before it’s defined in JavaScript?

Section titled “5. Can you call a function before it’s defined in JavaScript?”
greet();
sayHi();

function greet() {
    console.log("Hello");
}

const sayHi = function () {
    console.log("Hi");
};

Answer: Hello, then ReferenceError: Cannot access 'sayHi' before initialization

In the above example, you can see that:

  1. Remember the Creation Phase from the How JavaScript Works Behind the Scenes article? Before any code runs, JavaScript stores function declarations in memory, with the whole function.
  2. So greet() works even though we called it before writing it.
  3. sayHi is a function expression stored in a const. JavaScript knows the variable exists, but it doesn’t get a value until that line actually runs.
  4. Calling it before that line throws a ReferenceError.

So function declarations can be called before they’re defined, but function expressions and arrow functions can’t.

6. How do you make a function run only once?

Section titled “6. How do you make a function run only once?”

This is a classic closure question. Think of a “Pay Now” button. Even if the user clicks it twice, you only want to charge them once.

function once(fn) {
    let called = false;
    let result;

    return function (value) {
        if (!called) {
            called = true;
            result = fn(value);
        }
        return result;
    };
}

function pay(amount) {
    console.log(`Paid ₹${amount}`);
    return "success";
}

const payOnce = once(pay);

payOnce(500); // Paid ₹500
payOnce(500); // nothing happens
console.log(payOnce(500)); // success

In the above example, you can see that:

  1. once is a higher order function. It takes a function and returns a new one.
  2. The returned function closes over called and result.
  3. The first call sets called to true and runs pay.
  4. Every call after that skips pay and just returns the saved result.

7. What is currying in JavaScript? Make sum(1)(2)(3) return 6.

Section titled “7. What is currying in JavaScript? Make sum(1)(2)(3) return 6.”
function sum(a) {
    return function (b) {
        return function (c) {
            return a + b + c;
        };
    };
}

console.log(sum(1)(2)(3)); // 6

In the above example, you can see that:

  1. sum(1) returns a function that remembers a as 1.
  2. Calling that with (2) returns another function that remembers both a and b.
  3. Calling that with (3) finally adds all three together.

Currying means turning a function that takes many arguments into a chain of functions that each take one. It works because of closures, since every inner function remembers the values passed before it.

The same thing written with arrow functions looks much shorter:

const sum = (a) => (b) => (c) => a + b + c;

8. What is a higher order function? Write your own map().

Section titled “8. What is a higher order function? Write your own map().”

A higher order function is a function that takes another function as an argument, or returns a function, or both.

function myMap(arr, callback) {
    const result = [];

    for (let i = 0; i < arr.length; i++) {
        result.push(callback(arr[i], i));
    }

    return result;
}

const doubled = myMap([1, 2, 3], (num) => num * 2);
console.log(doubled); // [2, 4, 6]

In the above example, you can see that:

  1. myMap takes an array and a callback function.
  2. It loops over the array and calls the callback with each item and its index.
  3. Whatever the callback returns gets pushed into a new array.
  4. It returns the new array and never touches the original one, just like the real map().

Pretty neat, right? This question checks whether you understand that map() isn’t magic. It’s just a loop that calls your function.

9. What is an IIFE in JavaScript and why would you use one?

Section titled “9. What is an IIFE in JavaScript and why would you use one?”
const counter = (function () {
    let count = 0;

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

console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.count);       // undefined

In the above example, you can see that:

  1. An IIFE (Immediately Invoked Function Expression) is a function that runs as soon as it’s defined. Notice the () at the very end.
  2. It runs only once and gives back an object with an increment method.
  3. count lives inside the IIFE, so nothing outside can read or change it directly.
  4. increment is a closure, so it’s the only way to update count.

People use IIFEs to keep variables private and to avoid filling the global scope with variables.

You practiced how to:

  • Explain closures and predict what they remember
  • Solve the famous var vs let loop question
  • Tell function declarations from function expressions
  • Write once, a curried sum, and your own map()

Most closure questions are just asking one thing. Which variable does this function remember, and what’s inside that variable when the function actually runs?