← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Hoisting — var, let, const and function

JavaScript ES5 Intermediate
debt(d3/e1/b3/t7)
d3 Detectability Operational debt — how invisible misuse is to your safety net

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.

e1 Effort Remediation debt — work required to fix once spotted

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.

b3 Burden Structural debt — long-term weight of choosing wrong

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.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

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.

About DEBT scoring →

Also Known As

variable hoisting function hoisting TDZ

TL;DR

JavaScript hoists declarations to the top of their scope — var and function declarations are fully hoisted, while let and const are hoisted but remain in the Temporal Dead Zone until their declaration line.

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

let and const are not hoisted — they are hoisted to block scope but placed in the Temporal Dead Zone, so accessing them before declaration throws a ReferenceError rather than returning undefined.

Why It Matters

Hoisting explains why function declarations work anywhere in a file, why var can be used before assignment returning undefined silently, and why let/const are safer.

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

✗ Vulnerable
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() {};
✓ Fixed
// 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();

Added 22 Mar 2026
Edited 23 Mar 2026
Views 109
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 2 pings T 2 pings F 1 ping S 0 pings S 0 pings M
No pings yet today
No pings yesterday
Amazonbot 12 PetalBot 12 Ahrefs 9 Scrapy 8 ChatGPT 6 Google 5 Unknown AI 5 Perplexity 4 Sogou 2 Applebot 2 Brave Search 2 Majestic 1 Claude 1 Bing 1 Meta AI 1 Twitter/X 1
crawler 66 crawler_json 4 your_contextpost 1 pre-tracking 1
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
Closure javascript A closure is a function that remembers variables from the place where it was created, even after that outer code has finished running.

Closures let you create private state, build factory functions, and write callbacks that remember context. Understanding them unlocks most JavaScript patterns—from simple event handlers to module systems.

💡 If your closure captures the wrong value in a loop, switch from var to let—let creates a fresh binding per iteration.

Ask Codex about Closure →
Hoisting javascript Hoisting is JavaScript's behavior of moving variable and function declarations to the top of their scope before code runs, so you can sometimes use them before you write them.

Hoisting explains confusing 'undefined' values and ReferenceErrors that beginners hit constantly. Understanding it teaches you why order and scope matter in JavaScript.

💡 Always declare variables and functions before you use them — don't rely on hoisting to save you.

Ask Codex about Hoisting →
JavaScript javascript The programming language of the browser — it reads and modifies the page (the DOM), reacts to user events, and fetches data without reloading.

JavaScript is the only language browsers execute, so every interactive behaviour on the web goes through it. Its two defining traits — single-threaded event loop and loose typing (== coercion) — explain the majority of both its bugs and its design patterns.

💡 Default to const, use === always, and reach for let only when a value genuinely reassigns.

Ask Codex about JavaScript →
let javascript let declares a variable that can be reassigned later but only exists within its block (the nearest curly braces).

let replaced var as the default for changeable variables because its block scoping prevents accidental leaks and overwrites. Understanding let versus const is foundational to writing predictable, bug-free JavaScript.

💡 Default to const; only use let when you know the value must change.

Ask Codex about let →
var javascript var is the original JavaScript keyword for declaring variables. It creates a function-scoped variable that can be reassigned and redeclared, though modern code typically prefers let and const instead.

Understanding var explains why older JavaScript codebases behave unexpectedly and helps you appreciate why let and const became the modern standard. You'll encounter var in legacy code and need to know its quirks.

💡 Default to let or const in new code; use var only when maintaining legacy scripts that depend on its function-scoping behavior.

Ask Codex about var →
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Low
⚡ Quick Fix
Use const by default and let when reassignment is needed — never var. This eliminates hoisting surprises since const/let have block scope and TDZ protection
📦 Applies To
javascript ES5 web cli
🔗 Prerequisites
🔍 Detection Hints
var declarations inside loops or if blocks; function called before its declaration; accessing variable before let/const declaration line
Auto-detectable: ✓ Yes eslint typescript
🤖 AI Agent
Confidence: High False Positives: Medium ✓ Auto-fixable Fix: Low Context: Function


✓ schema.org compliant