PrepAhead
Start free
← All posts

JavaScript closures and scope quiz (10 questions)

June 6, 2026

  • JavaScript
  • Closures
  • Frontend

Closures and scope are where JavaScript interviews start shifting from surface syntax to runtime reasoning. The candidate usually is not being tested on vocabulary alone, but on whether they can predict what code actually sees and when.

If this set exposed weak spots, pair it with async questions next. A lot of real interview bugs happen when closures, timers, and promises all interact in the same snippet.

Question 1

What is a closure in JavaScript?

Pick an answer to see if you are correct
Reveal answer

Answer

A function bundled with access to variables from its lexical outer scope - A closure is a function that keeps access to variables from its lexical outer scope even after that outer function has returned.

Explanation

Closures are a normal part of how JavaScript functions work. They power callbacks, factory functions, memoization, and many module-like patterns.

Common interview notes

Strong answers use a short real example, such as a function returning another function that increments a private counter.

Question 2

In JavaScript, what does lexical scope mean?

Pick an answer to see if you are correct
Reveal answer

Answer

Variable access depends on where the function is defined in the source code - Lexical scope means variable access is determined by where a function is defined, not where it is called.

Explanation

JavaScript resolves identifiers by looking outward through the scope chain created by the source structure. This is why moving a function definition can change what variables it can see.

Common interview notes

A common follow-up is to compare lexical scope with dynamic scope and explain that JavaScript uses lexical scope.

Question 3

Which declaration is block-scoped?

Pick an answer to see if you are correct
Reveal answer

Answer

let - let is block-scoped.

Explanation

Variables declared with let and const exist only inside the nearest block. var is function-scoped, which is why it behaves differently inside loops and conditionals.

Example

if (true) {
  let count = 1;
}
// count is not defined here

Common interview notes

Interviewers often ask you to compare let and var inside a for loop with asynchronous callbacks.

Question 4

Why does this classic loop produce repeated values with var and setTimeout?

Pick an answer to see if you are correct
Reveal answer

Answer

var creates one shared function-scoped binding that each callback closes over - With var, each callback closes over the same function-scoped binding, so they all read the final loop value later.

Explanation

The issue is not the timer itself but the shared binding created by var. Using let in the loop creates a fresh block-scoped binding for each iteration.

Example

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}
// logs 3, 3, 3

Common interview notes

A strong follow-up answer explains both the let fix and the IIFE fix for older code.

Question 5

What is hoisting best described as?

Pick an answer to see if you are correct
Reveal answer

Answer

The language's creation of bindings before execution, with different initialization behavior by declaration type - Hoisting is the creation of bindings before execution, with different behavior depending on whether you used var, let, const, or function declarations.

Explanation

Function declarations are available earlier in their scope, var is hoisted and initialized to undefined, and let or const exist in the temporal dead zone until their declaration is evaluated. Interviews usually care about this behavior, not the metaphor alone.

Common interview notes

Good answers mention that hoisting does not mean let and const are safely usable before their declaration line.

Question 6

What happens if you read a let variable before its declaration in the same scope?

Pick an answer to see if you are correct
Reveal answer

Answer

It throws a ReferenceError - Reading a let variable before its declaration throws a ReferenceError.

Explanation

That behavior comes from the temporal dead zone, the period between entering the scope and executing the declaration. const behaves the same way with respect to early access.

Common interview notes

This question often checks whether the candidate incorrectly generalizes var behavior to let and const.

Question 7

Which pattern is a practical use of closures?

Pick an answer to see if you are correct
Reveal answer

Answer

Hiding private state inside a factory function - Closures are often used to hide private state inside a factory function.

Explanation

A returned function can still access variables from the outer function even after that outer function finishes. This is a simple way to encapsulate state without exposing it directly on an object.

Example

function createCounter() {
  let count = 0;
  return () => ++count;
}

Common interview notes

A useful follow-up is when a class or module would be clearer than closure-based private state.

Question 8

Inside a nested function, JavaScript looks up a missing variable name by searching where first?

Pick an answer to see if you are correct
Reveal answer

Answer

The current scope, then outer lexical scopes outward - JavaScript looks in the current scope first, then walks outward through outer lexical scopes.

Explanation

This chain of nested scopes is what allows inner functions to use variables defined outside them. If the name is not found anywhere in the scope chain, a ReferenceError occurs when the code runs.

Common interview notes

Strong answers distinguish the lexical scope chain from object prototype lookup, which is a different mechanism.

Question 9

Which statement about closures and memory is most accurate?

Pick an answer to see if you are correct
Reveal answer

Answer

Closures can keep referenced outer variables alive as long as the inner function remains reachable - Closures can keep referenced outer variables alive while the closure is still reachable.

Explanation

This is not a problem by itself, but it matters when long-lived callbacks retain large objects or DOM references unnecessarily. Interviews sometimes use this question to bridge into performance or leak debugging.

Common interview notes

A good follow-up is to describe one real case, such as an event handler retaining stale component data.

Question 10

Why is let usually preferred over var in modern interview answers?

Pick an answer to see if you are correct
Reveal answer

Answer

let avoids accidental function-scoped sharing and is easier to reason about - let is usually preferred because block scope matches developer expectations better and avoids many var-related footguns.

Explanation

let reduces bugs caused by unintended sharing across loops and blocks, especially with asynchronous callbacks. It also makes code easier to explain during interviews because the scoping model is more predictable.

Common interview notes

A strong answer mentions const as the default for bindings that should not be reassigned, with let reserved for actual rebinding.

Full answer key

Review every answer in one place, with explanations and interview tips below.

1. What is a closure in JavaScript?

Answer summary

A function bundled with access to variables from its lexical outer scope — A closure is a function that keeps access to variables from its lexical outer scope even after that outer function has returned.

Closures are a normal part of how JavaScript functions work. They power callbacks, factory functions, memoization, and many module-like patterns.

Interview tip: Strong answers use a short real example, such as a function returning another function that increments a private counter.

2. In JavaScript, what does lexical scope mean?

Answer summary

Variable access depends on where the function is defined in the source code — Lexical scope means variable access is determined by where a function is defined, not where it is called.

JavaScript resolves identifiers by looking outward through the scope chain created by the source structure. This is why moving a function definition can change what variables it can see.

Interview tip: A common follow-up is to compare lexical scope with dynamic scope and explain that JavaScript uses lexical scope.

3. Which declaration is block-scoped?

Answer summary

let — let is block-scoped.

Variables declared with let and const exist only inside the nearest block. var is function-scoped, which is why it behaves differently inside loops and conditionals.

if (true) {
  let count = 1;
}
// count is not defined here

Interview tip: Interviewers often ask you to compare let and var inside a for loop with asynchronous callbacks.

4. Why does this classic loop produce repeated values with var and setTimeout?

Answer summary

var creates one shared function-scoped binding that each callback closes over — With var, each callback closes over the same function-scoped binding, so they all read the final loop value later.

The issue is not the timer itself but the shared binding created by var. Using let in the loop creates a fresh block-scoped binding for each iteration.

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}
// logs 3, 3, 3

Interview tip: A strong follow-up answer explains both the let fix and the IIFE fix for older code.

5. What is hoisting best described as?

Answer summary

The language's creation of bindings before execution, with different initialization behavior by declaration type — Hoisting is the creation of bindings before execution, with different behavior depending on whether you used var, let, const, or function declarations.

Function declarations are available earlier in their scope, var is hoisted and initialized to undefined, and let or const exist in the temporal dead zone until their declaration is evaluated. Interviews usually care about this behavior, not the metaphor alone.

Interview tip: Good answers mention that hoisting does not mean let and const are safely usable before their declaration line.

6. What happens if you read a let variable before its declaration in the same scope?

Answer summary

It throws a ReferenceError — Reading a let variable before its declaration throws a ReferenceError.

That behavior comes from the temporal dead zone, the period between entering the scope and executing the declaration. const behaves the same way with respect to early access.

Interview tip: This question often checks whether the candidate incorrectly generalizes var behavior to let and const.

7. Which pattern is a practical use of closures?

Answer summary

Hiding private state inside a factory function — Closures are often used to hide private state inside a factory function.

A returned function can still access variables from the outer function even after that outer function finishes. This is a simple way to encapsulate state without exposing it directly on an object.

function createCounter() {
  let count = 0;
  return () => ++count;
}

Interview tip: A useful follow-up is when a class or module would be clearer than closure-based private state.

8. Inside a nested function, JavaScript looks up a missing variable name by searching where first?

Answer summary

The current scope, then outer lexical scopes outward — JavaScript looks in the current scope first, then walks outward through outer lexical scopes.

This chain of nested scopes is what allows inner functions to use variables defined outside them. If the name is not found anywhere in the scope chain, a ReferenceError occurs when the code runs.

Interview tip: Strong answers distinguish the lexical scope chain from object prototype lookup, which is a different mechanism.

9. Which statement about closures and memory is most accurate?

Answer summary

Closures can keep referenced outer variables alive as long as the inner function remains reachable — Closures can keep referenced outer variables alive while the closure is still reachable.

This is not a problem by itself, but it matters when long-lived callbacks retain large objects or DOM references unnecessarily. Interviews sometimes use this question to bridge into performance or leak debugging.

Interview tip: A good follow-up is to describe one real case, such as an event handler retaining stale component data.

10. Why is let usually preferred over var in modern interview answers?

Answer summary

let avoids accidental function-scoped sharing and is easier to reason about — let is usually preferred because block scope matches developer expectations better and avoids many var-related footguns.

let reduces bugs caused by unintended sharing across loops and blocks, especially with asynchronous callbacks. It also makes code easier to explain during interviews because the scoping model is more predictable.

Interview tip: A strong answer mentions const as the default for bindings that should not be reassigned, with let reserved for actual rebinding.

Try each question on your own, then open "Reveal answer" for the full write-up. For tailored practice and Check feedback on open-ended responses, use PrepAhead in the app - not on blog pages.