JS

runtime.js

One spine: the evolution of JavaScript

Pick an era, expand a concept, and see where it lands in today's runtimes. Every snippet can be dropped straight into the sandboxed console — the event loop panel then shows real, instrumented execution, not a looping animation.

Pre-ES6

ES51995 – 2014

One function scope, one binding keyword, and callbacks all the way down. Everything that came later is a reaction to this era's sharp edges.

`var` is function-scoped and hoisted: the binding exists before the line that declares it, initialised to undefined. Loops that capture `var` capture one shared binding.

console.log(typeof greeting); // "undefined", not a ReferenceError
var greeting = "hi";

for (var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log("var i =", i); // 3, 3, 3 — one shared binding
  }, 0);
}
Where the top-level scope lives
V8In a classic script, a top-level `var` becomes a property of the global object; in a module it stays module-local. `let`, `const`, and `class` never leak onto the global object.
Node.jsEvery CommonJS file is wrapped in a function, so top-level `var` is module-local, not global. ESM files follow the spec and are strict by default.
DenoAll modules are ESM from day one: no CommonJS wrapper, no implicit globals — a top-level `var` is always contained.
BunDual-mode like Node — CJS files get the wrapper, ESM files get spec scoping. Neither leaks `var` onto the global object.

Interview gotchas

15 genuinely tricky, well-known snippets — event-loop ordering, closures in loops, and `this`-binding traps. Open one, read the gotcha, then drop it straight into the sandboxed console to watch it really run.

Event loop
Closures & scope
this binding
Promises & async
Coercion & equality
Built-in traps