For each block below, predict the output before running it. Each question is a real interview pattern.
Q1 โ var hoisting: declaration but not initialization
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
undefined
5var declarations are hoisted to the top of their function/global scope but their value is not. The engine treats it as:
var a; // hoisted โ exists but is undefined
console.log(a); // undefined
a = 5;
console.log(a); // 5Q2 โ let/const: Temporal Dead Zone
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
ReferenceError: Cannot access 'x' before initializationlet and const are hoisted but placed in the Temporal Dead Zone โ they exist but are inaccessible until the declaration line is evaluated. Accessing them before that line throws a ReferenceError.
Q3 โ function declaration vs expression
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"foo"
undefined- Function declarations are fully hoisted โ both the name and the body. You can call
foo()before its definition. - Function expressions (
var bar = functionโฆ) hoist only thevar barโ the variable isundefineduntil that line runs. Callingbar()before line 5 throwsTypeError: bar is not a function.
Q4 โ var in a block scope
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
1
"undefined"var ignores block scope โ x leaks out of the block into the surrounding function/global scope. let is block-scoped, so y doesnโt exist outside the {}. typeof on an undeclared variable returns "undefined" (not a ReferenceError โ a special case).
Q5 โ hoisting order: function vs var with same name
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"function"
"string"When a variable and a function declaration share the same name, the function declaration wins during hoisting โ it takes precedence over var. So before any code runs, foo is the function. After foo = 'variable' runs on line 2, foo becomes the string.
Q6 โ function declaration inside a block (non-strict mode)
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"undefined" (outer, before block)
"function" (inside block, after hoisting within block)
"function" (inside block, after declaration)
"function" (outer, after block โ hoisted out in non-strict mode)In non-strict mode, function declarations inside blocks have complex legacy behavior: the declaration is hoisted to the top of the block, but the name is also created in the outer scope (as undefined initially), and when execution passes the declaration line, the outer binding is updated. This is an engine-specific quirk โ in strict mode, block-scoped functions stay in the block. Avoid block-level function declarations.
Q7 โ var in a for loop
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
3
3
3var is function-scoped โ there is one shared i across all iterations. By the time the setTimeout callbacks fire (after the loop completes), i is 3. All three closures close over the same binding.
Q8 โ let fixes the loop bug
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
0
1
2let is block-scoped and creates a fresh binding per iteration. Each callback closes over its own independent j.
Q9 โ hoisting with re-declaration
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
2
2Both var a declarations are in the same function/global scope โ var allows re-declaration and they both refer to the same variable. The inner block updates the shared a to 2, so both logs print 2.
Q10 โ const in a block
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
2
1const is block-scoped โ the inner const x = 2 is a completely separate binding from the outer const x = 1. No error; each block has its own x.
Q11 โ function parameter shadowing
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"local"
"global"The parameter x shadows the outer x within the function body. The global x is untouched.
Q12 โ class declaration hoisting
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
ReferenceError: Cannot access 'MyClass' before initializationclass declarations are hoisted but placed in the TDZ, just like let/const. You cannot use a class before its declaration. (The second console.log never runs.)
var brings undefined. let, const, and class are in the TDZ. var escapes blocks; everything else doesnโt.