Hoisting — var, let, const and function
debt(d3/e1/b3/t7)
Closest to 'default linter catches the common case' (d3). ESLint (listed in detection_hints.tools) has rules like no-var, no-use-before-define, and prefer-const that catch the most common hoisting mistakes. TypeScript also catches TDZ violations at compile time. These are mainstream tools that catch the common cases without specialist configuration.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix is explicit: replace var with const/let throughout. This is a mechanical, largely automated substitution (ESLint --fix can handle many cases). Switching to arrow functions from hoisted function declarations is similarly local. No cross-file architectural changes needed.
Closest to 'localised tax' (b3). The concept applies to web and cli contexts broadly, but once a codebase adopts const/let as a standard (which is now idiomatic JS), the ongoing burden is low. Legacy codebases using var everywhere carry a persistent but localized tax within affected files. It does not reshape architecture or slow many work streams.
Closest to 'serious trap' (t7). The misconception field identifies the canonical trap: developers believe let/const are not hoisted at all, when they ARE hoisted but placed in the Temporal Dead Zone, causing a ReferenceError instead of the expected undefined. This contradicts the intuition from var behavior and from how similarly-named constructs in other languages behave. The arrow-function-not-hoisted gotcha adds another layer of contradiction for devs familiar with function declarations.
Also Known As
TL;DR
Explanation
Function declarations are fully hoisted: you can call a function before its declaration. var declarations are hoisted but initialised to undefined — accessing before assignment gives undefined, not an error. let and const are technically hoisted to block scope but live in the Temporal Dead Zone (TDZ) until their declaration — accessing them before declaration throws a ReferenceError. PHP has no hoisting — functions and variables must be declared before use.
Common Misconception
Why It Matters
Common Mistakes
- Using var inside a loop expecting block scope (it has function scope)
- Accessing a let variable before declaration expecting undefined
- Relying on function hoisting then switching to arrow functions (not hoisted)
Code Examples
console.log(x); // undefined (not ReferenceError)
var x = 5;
foo(); // Works — function declarations are fully hoisted
function foo() { console.log('hello'); }
bar(); // TypeError: bar is not a function
var bar = function() {};
// Avoid hoisting confusion — declare before use:
const x = 5;
console.log(x);
// Function declarations are fine to call before definition
// but prefer declaring at top for clarity
// Always use const/let — no hoisting surprises:
const bar = () => {};
bar();