Interview Q&A / JavaScript

BeginnerIn-depth3 min readUpdated 2 Oct 2026

What is the difference between var, let and const? Explain hoisting and the temporal dead zone.

SHORT ANSWER

var is function-scoped and is hoisted with the value undefined. let and const are block-scoped and are hoisted too, but cannot be used before their declaration line; that gap is the temporal dead zone. const also cannot be reassigned, though an object it holds can still be changed.

Explain it simply

Think of a classroom attendance register. Before the class starts, the teacher writes every student's name in the register. That is hoisting: JavaScript reads your code first and notes every variable name in the scope before running a single line.

What happens if someone calls a name early is different:

  • With var, the name is in the register with a blank next to it. Asking for it early gives you undefined, with no error.
  • With let and const, the name is in the register but marked "not arrived yet". Asking for it early is an error. The time between the start of the scope and the line where the variable is declared is called the temporal dead zone (TDZ).

The other big difference is scope. var belongs to the whole function. let and const belong to the nearest pair of curly braces { }, such as an if block or a loop.

Example

Hoisting, side by side:

js
console.log(price); // prints undefined (var is hoisted with undefined)
var price = 100;

console.log(total); // ReferenceError: Cannot access 'total' before initialization
let total = 200;

Block scope, the TDZ and const, checked by running:

js
if (true) {
  var fromVar = 1;
  let fromLet = 2;
}
console.log(typeof fromVar, typeof fromLet); // Output: number undefined

try {
  console.log(score);
  let score = 10;
} catch (e) {
  console.log(e.name); // Output: ReferenceError
}

const user = { name: "Asha" };
user.name = "Ravi"; // allowed: we change the object, not the variable
console.log(user.name); // Output: Ravi

try {
  user = { name: "Kiran" }; // not allowed: reassigning a const
} catch (e) {
  console.log(e.name); // Output: TypeError
}

How it works

varletconst
ScopeFunctionBlockBlock
HoistedYes, set to undefinedYes, but in the TDZYes, but in the TDZ
Re-declare in same scopeAllowedErrorError
ReassignAllowedAllowedError
Must initialise at declarationNoNoYes

Function declarations are hoisted completely, body included, which is why you can call them above the line where they are written. Function expressions assigned to let or const follow the TDZ rules.

Real-world use

Modern style is: use const by default, let when the value must change (a loop counter, a running total), and avoid var. This makes code easier to read, because a reader knows a const binding never points to something else.

Common mistakes

  • Believing const makes an object or array frozen. It only stops reassignment. Use Object.freeze for a shallow freeze.
  • Saying let and const are "not hoisted". They are hoisted; the TDZ is what stops early access.
  • Using var in a loop with callbacks, so every callback sees the final value.
  • Thinking typeof is always safe. typeof x on a variable in its TDZ still throws.

What to say in the interview

"var is function-scoped, can be re-declared, and is hoisted with the value undefined, so reading it early gives undefined. let and const are block-scoped. They are also hoisted, but they stay uninitialised until their declaration runs, and accessing them before that throws a ReferenceError; that period is the temporal dead zone. const cannot be reassigned, but if it holds an object, the object's properties can still change. I use const by default and let only when I need to reassign."

Follow-up questions

  • Why does a for loop with var and setTimeout print the same number three times?
  • Is const arr = []; arr.push(1) valid?
  • Are function declarations and function expressions hoisted the same way?

Go deeper

Read these once the basics above feel easy.

At the top level of a classic script, var creates a property on the global object (window.price in a browser), while let and const do not. In a for (let i = 0; ...) loop, the engine creates a new binding of i for each iteration and copies the value forward, which is why closures in the loop each see their own i. See closures for that example.

#variables#scope#hoisting#es6

Related questions

Practise more JavaScript questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open JavaScript quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.