Detailed explanation
JavaScript provides var, let and const for declaring variables. Their main differences are scope, behaviour before initialisation, redeclaration and reassignment. Scope determines where a variable is accessible, while reassignment changes the value associated with its name. These differences matter because they affect accidental overwrites, access before declaration and predictable code. In interviews, explain the rules and then demonstrate them with a small example rather than simply saying that let and const are newer.
var is function-scoped: a declaration inside a function belongs to that function, even when written inside an if block. let and const are block-scoped, so braces in an if statement or loop can limit their visibility. In the given example, a remains accessible after the if block, but b does not. Accessing b outside its block throws a ReferenceError because that binding is outside the current scope, not because it is in the temporal dead zone. At the top level of a classic browser script, var also creates a global-object property; let and const do not. Module scope behaves differently.
Before code executes, JavaScript sets up bindings for declarations. A var binding is initialised to undefined, so reading it before its declaration usually returns undefined; the later assignment has not run yet. let and const bindings are also created early, but remain uninitialised until their declarations are evaluated. This interval is the temporal dead zone, and accessing the binding during it throws a ReferenceError. Therefore, saying that let and const are not hoisted is misleading. A declaration such as let x; initialises x to undefined when execution reaches it.
var allows repeated declarations in the same scope, while let and const generally reject same-scope redeclaration with a SyntaxError. Both var and let allow reassignment. const requires an initialiser in an ordinary declaration and prevents reassignment of the binding, not mutation of the referenced object. Thus, o.n = 2 is allowed, but o = {} throws a TypeError. Prefer const when reassignment is unnecessary, use let when it is needed, and understand var when reading older code.
Key points to remember
- var is function-scoped; let and const are block-scoped.
- var is initialised to undefined before execution reaches its declaration.
- let and const remain in the temporal dead zone until their declarations initialise them.
- var permits same-scope redeclaration; let and const generally do not.
- const prevents binding reassignment, not changes to object properties or array elements.
Common mistakes candidates make
- Saying let and const are not hoisted instead of explaining their uninitialised bindings and temporal dead zone.
- Assuming const makes an object or array immutable.
- Calling an out-of-scope ReferenceError a temporal-dead-zone error.
Likely follow-up questions
What happens when typeof is used during the temporal dead zone?
typeof throws a ReferenceError when it accesses a let or const binding in its temporal dead zone. In contrast, typeof on an undeclared identifier normally returns "undefined".
Why does let behave differently from var in loops with callbacks?
In a loop such as for (let i = 0; i < 3; i++), each iteration gets a separate binding for i. With var, callbacks share one binding, so callbacks executed after the loop typically observe its final value.
How can you prevent changes to an object declared with const?
Use Object.freeze() to prevent additions, removals and changes to the object's own properties. Freezing is shallow, so nested objects can still change unless they are frozen separately.
Interview tip: Compare scope, initialisation and reassignment in that order, then use the supplied examples to show the observable differences.
