Katkat

Predict JavaScript let and var Behavior

AmazonFrontend Engineer · Onsite

Last 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

  1. State the Output: Write the exact sequence of values or errors logged to the console for each snippet.
  2. Explain the Mechanics: Explain why each output occurs by discussing:
    • Creation Phase vs Execution Phase: How var and let are 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 for var vs let.
    • Loop Binding Semantics: How ECMAScript specifies the creation of bindings across loop iterations for var compared to let.

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?