Katkat

Explain JavaScript Scope, Closures, Timers, and the Event Loop

AppleFrontend Engineer · Technical Screen

Last updated

Tests deep understanding of the JavaScript runtime, specifically lexical scope, closures, the distinction between task and microtask queues in the event loop, and browser script loading mechanics.

Problem Overview

During a frontend technical screen, you are asked to evaluate JavaScript runtime mechanics, analyze asynchronous code execution order, and explain the browser's execution lifecycle.

Part 1: Event Loop & Queue Execution Order

Predict the exact console output of the following snippet in order, and explain the step-by-step role of the call stack, microtask queue, and task (macrotask) queue:

console.log('1');

setTimeout(() => {
  console.log('2');
  Promise.resolve().then(() => console.log('3'));
}, 0);

new Promise((resolve) => {
  console.log('4');
  resolve();
}).then(() => {
  console.log('5');
});

queueMicrotask(() => {
  console.log('6');
});

console.log('7');

Part 2: Scope, Closures, and Timers

Consider the following two loops:

// Snippet A
for (var i = 0; i  console.log('A:', i), 100);
}

// Snippet B
for (let j = 0; j  console.log('B:', j), 100);
}
  1. What does each loop output, and why? Explain how execution contexts, lexical environments, and closures differ between var and let in this context.
  2. Explain the Temporal Dead Zone (TDZ) and how it affects let and const declarations compared to var hoisting.
  3. Show two ways to refactor Snippet A to print 0, 1, 2 without changing var to let.

Part 3: Script Execution and the DOM

Explain how the browser processes , , and `` during HTML parsing:

  • How does each attribute affect HTML parser blocking?
  • In what order are scripts executed relative to one another and relative to DOMContentLoaded?

Hints

Hint 1

Remember that microtasks (Promise reactions, queueMicrotask) are drained completely after each task and before the browser renders or processes the next macrotask.

Hint 2

A `var` variable is function-scoped and shared across iterations, whereas `let` creates a distinct lexical binding for each loop iteration.

Hint 3

Scripts marked with `defer` preserve document order and execute after parsing completes but before `DOMContentLoaded`, whereas `async` scripts execute as soon as they finish downloading.

Follow-up questions

  • What happens if a microtask recursively enqueues another microtask? How does that impact macrotasks and browser UI repaints?
  • Where does `requestAnimationFrame` fit into the event loop cycle relative to task execution and the browser rendering pipeline?
  • How does the minimum clamping delay (e.g., 4ms after nesting) in `setTimeout` affect high-frequency scheduling compared to `MessageChannel` or `postMessage`?