Intermediate11 questionsFull Guide

JavaScript Closure Interview Questions

Closures are the most frequently tested JavaScript concept. Master them with real interview questions, answers, and code examples.

The Mental Model

When you create a function inside another function, JavaScript gives the inner function a backpack. It automatically packs up every variable it can see at the moment of creation — and carries that backpack everywhere it goes, forever. Even after the outer function has finished and is gone from memory, the inner function still has its backpack. Still has those variables. That's a closure. The key insight: functions remember where they were born, not where they run.

The Explanation

Why closures exist

JavaScript uses lexical scoping — a function's scope is determined by where it's written in the code, not where it's called from. Closures are the natural consequence of this combined with first-class functions.

function outer() {
  const message = 'I am in the backpack'

  return function inner() {
    console.log(message) // works even after outer() is gone
  }
}

const fn = outer()  // outer() runs and returns — 'message' should be gone…
fn()                // 'I am in the backpack' — but it's not. Closure.

Example 1 — Counter (closures as private state)

The most common real pattern. count is completely private — no way to set it or read it from outside except through the methods you expose.

function createCounter() {
  let count = 0  // private — nobody outside can touch this

  return {
    increment() { count++ },
    decrement() { count-- },
    value()     { return count }
  }
}

const counter = createCounter()
counter.increment()
counter.increment()
counter.decrement()
console.log(counter.value()) // 1

console.log(count) // ReferenceError — count doesn't exist out here

Example 2 — Function factory (closures generating functions)

Each call to multiplier() creates a new closure with a different factor in its backpack. They're independent — changing one doesn't affect the others.

function multiplier(factor) {
  return function(number) {
    return number * factor  // 'factor' is in the backpack
  }
}

const double = multiplier(2)
const triple = multiplier(3)

console.log(double(5))  // 10
console.log(triple(5))  // 15

The classic gotcha — the loop problem

This trips up experienced developers. Every interviewer uses it.

for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i)
  }, 1000)
}

// Most people expect: 0, 1, 2
// What actually prints: 3, 3, 3

Why: var is function-scoped — there's only one i variable for the whole loop. All three closures point to the same i. By the time setTimeout fires, the loop is done and i is 3.

// Fix 1 — use let (creates a new binding per iteration)
for (let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i)  // 0, 1, 2 ✓
  }, 1000)
}

// Fix 2 — IIFE (manually create a new scope)
for (var i = 0; i < 3; i++) {
  (function(j) {
    setTimeout(function() {
      console.log(j)  // 0, 1, 2 ✓
    }, 1000)
  })(i)
}

The junior vs senior answer

A junior answer quotes the definition: "A closure is when a function has access to its outer scope's variables even after the outer function has returned." Technically correct. Not memorable.

A senior answer explains the backpack analogy, demonstrates the loop problem without being asked, and mentions React hooks or the module pattern as real-world usage. That's what gets you hired.

Common Misconceptions

⚠️

Closures copy the variable value" — Wrong. They hold a reference to the variable. If the variable changes after the closure is created, the closure sees the new value. This is exactly why the var loop problem happens — all closures share the same reference to i.

⚠️

Closures only work when you use return" — Wrong. Any function that accesses an outer variable is a closure — callbacks, event handlers, methods. The backpack forms at creation time, not at return.

⚠️

Closures cause memory leaks" — They can, if you close over large objects you don't need and never release the reference. But closures themselves are not leaks. Used correctly they're completely fine and used everywhere.

Where You'll See This in Real Code

React's useState hook — the updater function closes over the current state value. This is why stale closures happen in useEffect: the callback captures the value of state at render time, not the latest value. Fix with the functional updater form: setCount(prev => prev + 1).

Event handlers — addEventListener callbacks always form closures. When you write btn.addEventListener('click', () => console.log(label)), the callback closes over label from the outer scope and remembers it forever, even after the setup function returns.

The module pattern — before ES modules existed, developers used IIFEs to create private state. The returned object has access to private variables through closure, but outside code can't touch them directly. Still used in many libraries today.

Memoization / caching — a memoize function closes over a cache object. Every call to the returned function can read and write to that same cache, persisting results between calls without any global variables.

Interview Cheat Sheet

  • A closure is a function that retains access to its outer scope even after the outer function returns
  • Closures are created every time a function is created — at function creation time
  • Classic trap: var in a for-loop closure captures the final value (use let or IIFE to fix)
  • Used in: module pattern, memoization, factory functions, partial application
  • Every function in JS is a closure (it closes over its lexical environment)
💡

How to Answer in an Interview

  • 1.Always draw a mental stack frame diagram when explaining closures
  • 2.Be ready to fix the classic "print 0-9 in loop" bug — it's asked at 80% of mid-level interviews
  • 3.Connect closures to real patterns you've used: debounce, memoization, React's useState
  • 4.Distinguish closure (concept) from IIFE (pattern that uses closures)
📖 Deep Dive Articles
Arrow Functions vs Regular Functions in JavaScript: 6 Key Differences9 min readTop 50 JavaScript Interview Questions (With Deep Answers)18 min readJavaScript Scope Explained: Lexical Scope, Scope Chain, and How Variables Are Found10 min readJavaScript Hoisting Explained: What Actually Moves, What Doesn't, and Why It Matters9 min readJavaScript Prototypes Explained: The Object Model Behind Every Class and Method10 min readJavaScript `this` Keyword Explained: Five Rules, Zero Guessing10 min readJavaScript Closures: What They Actually Are (And Why Interviews Love Them)10 min readJavaScript Output Questions: 30 Tricky Examples That Test Real Understanding14 min read

Practice Questions

11 questions
#01

Explain closures with a practical example.

🟢 EasyCore JS💡 A function that remembers its outer scope after the outer function returns
#02

What is the difference between call, apply, and bind?

🟢 EasyFunctions PRO💡 All set "this" — call=comma, apply=array, bind=returns new fn
#03

Classic var in loop closure

🟢 EasyClosures & Scope
#04

Stale closure in React useEffect

🟡 MediumClosure TrapsDebug
#05

Memoization closure caching wrong scope

🔴 HardClosure TrapsDebug
#06

let in loop closure (fix)

🟢 EasyClosures & Scope
#07

Closure counter

🟡 MediumClosures & Scope
#08

IIFE closure

🟡 MediumClosures & Scope
#09

Closure variable lookup

🔴 HardClosures & Scope
#10

Shared closure mutation

🔴 HardClosures & Scope
#11

bind creates new function

🔴 Hard'this' Binding

Related Topics

JavaScript "this" Keyword Interview Questions
Intermediate·6–10 Qs
JavaScript Hoisting Interview Questions
Intermediate·4–8 Qs
JavaScript Scope Interview Questions
Beginner·4–6 Qs
🎯

Can you answer these under pressure?

Reading answers is not the same as knowing them. Practice saying them out loud with AI feedback — that's what builds real interview confidence.

Practice Free →Try Output Quiz