Pre-ES6
ES51995 – 2014One 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);
}| V8 | In 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.js | Every 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. |
| Deno | All modules are ESM from day one: no CommonJS wrapper, no implicit globals — a top-level `var` is always contained. |
| Bun | Dual-mode like Node — CJS files get the wrapper, ESM files get spec scoping. Neither leaks `var` onto the global object. |