Predict JavaScript let and var Behavior
AmazonFrontend Engineer · OnsiteLast updated
Tests deep understanding of JavaScript variable declarations (var vs let), focusing on hoisting, the Temporal Dead Zone (TDZ), block vs function scoping, and per-iteration lexical bindings in asynchronous loops.
Problem Description
Analyze the three JavaScript code snippets below. For each snippet, determine the exact console output (including any runtime errors) and provide a technical explanation grounded in JavaScript's execution model.
Snippet 1: Hoisting and the Temporal Dead Zone
function testHoisting() {
console.log(a);
console.log(b);
var a = 10;
let b = 20;
}
testHoisting();
Snippet 2: Block Scoping and Redeclaration
var x = 1;
let y = 2;
{
var x = 100;
let y = 200;
console.log(x, y);
}
console.log(x);
console.log(y);
console.log(typeof z);
Snippet 3: Closures and Asynchronous Loop Execution
for (var i = 0; i console.log('var:', i), 10);
}
for (let j = 0; j console.log('let:', j), 10);
}
Tasks
- State the Output: Write the exact sequence of values or errors logged to the console for each snippet.
- Explain the Mechanics: Explain why each output occurs by discussing:
- Creation Phase vs Execution Phase: How
varandletare registered and initialized in memory during context creation. - Temporal Dead Zone (TDZ): What TDZ is and how the engine enforces it for
let. - Lexical Environment vs Variable Environment: How blocks
{}affect variable lookup and reassignment forvarvslet. - Loop Binding Semantics: How ECMAScript specifies the creation of bindings across loop iterations for
varcompared tolet.
- Creation Phase vs Execution Phase: How
Hints
Hint 1
Variables declared with let are hoisted to the top of their containing block, but accessing them before their declaration line triggers a ReferenceError rather than evaluating to undefined.
Hint 2
A block statement does not create a new variable environment for var, meaning var declarations inside a block mutate or shadow outer function/global variables.
Hint 3
The ECMAScript specification mandates a fresh lexical binding for each iteration of a for (let ...) loop, while for (var ...) shares a single mutable binding across all iterations.
Follow-up questions
- How does the behavior change if we declare const i = 0 in a standard for loop header instead of let?
- How would you preserve loop index values in an ES5 environment where let and const are unavailable?
- What is the difference between global variables declared with var versus let in browser environments regarding the window object?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.