Topic 41 of 59 JavaScript Functions Interactive Tutorial

JavaScript Hoisting: Understanding Variables and Functions Before Execution

23 mins read Last updated: 22 Aug 2026 14453 views
Quick Summary & Key Takeaway Target Skill Level: Beginner to Advanced ES6+

Bottom-Line Answer: JavaScript (JS) is a high-level, single-threaded, just-in-time (JIT) compiled programming language with first-class functions that conforms to the ECMAScript specification. It powers dynamic client-side web interactivity alongside HTML and CSS, and executes backend server runtimes via Node.js, Deno, and Bun.

Target Audience: Frontend developers, full-stack engineers, students & QA testers.
Prerequisites: Basic HTML semantics & fundamental CSS styling rules.
Primary Use Cases: Dynamic web UI, DOM manipulation, asynchronous REST APIs, Node.js backend services.

What is JavaScript Hoisting? Core Concept & Direct Summary

Core Objective & Problem Statement

What is hoisting in JavaScript?

Direct Answer Summary
Hoisting is JS behavior where variable and function declarations are moved to the top of their containing scope during compilation.

How Does JavaScript Hoisting Work? In-Depth Mechanics & Architecture

Function declarations are hoisted with initializations; var is hoisted with undefined; let/const are hoisted in TDZ.

Here are two pieces of code. One works. One explodes. Can you guess which is which?

script.js
Run Online
// Code A:console.log(message);          // ???var message = "Hello! 👋";
// Code B:sayHello();                    // ???function sayHello() {  console.log("Hello! 👋");}

The twist:Code A printsundefined(no error!), while Code B runs perfectly — the function executesbeforeits own definition. 🤯

Both behaviors come from the same JavaScript mechanism:hoisting— the reason JavaScript seems to "know about" variables and functions before it reaches their lines. It's one of the most-asked interview topics in all of JavaScript, and one of the most misunderstood.

In this lesson, you'll learn what hoistingactuallyis (it's not what most tutorials say!), howvar,let,const, and functions each behave differently, and the mysterioustemporal dead zonethat's been name-dropped sinceLesson 4. Let's lift the curtain. 🎩


What Is Hoisting? (The Truth, Not the Myth) 🎈

The popular myth:"JavaScript physically moves declarations to the top of your file." ❌ Not true — your code never moves.

What actually happens:JavaScript runs your code intwo phases:

Phase 1: The Creation Phase 📋

Before executing a single line, JavaScript scans the entire scope andregisters all declarations— setting aside memory for every variable and function:

  • vardeclarations → registered AND initialized toundefined
  • let/constdeclarations → registered but leftuninitialized💀
  • Function declarations → registeredcompletely(name + entire body!)

Phase 2: The Execution Phase ▶️

Now your code runs line by line — but the declarations are already in memory. That's why they're "known" before their lines execute.

Hoisting = the creation phase preparing memory before execution begins.Nothing moves; everything ispre-registered.


Hoisting with var: The Ghost Variable 👻

script.js
Run Online
console.log(message);
// undefined — not an error! 😮var message = "Hello!";
console.log(message);
// "Hello!" ✅

Whyundefinedand not an error?During the creation phase,var messagewas registered and initialized toundefined. So at execution time, the variableexists— it just holds the placeholderundefined.

How JavaScript effectively treats it:

script.js
Run Online
var message;
// 👻 hoisted + initialized to undefinedconsole.log(message);          // undefinedmessage = "Hello!";            // the ASSIGNMENT stays in placeconsole.log(message);          // "Hello!"

⚠️Key insight:only thedeclarationis hoisted — theassignment stays put.This is the #1 hoisting misunderstanding in interviews.


Hoisting with let & const: The Temporal Dead Zone 💀

Now watch the same code withlet:

script.js
Run Online
console.log(message);
// ❌ ReferenceError: Cannot access 'message' before initializationlet message = "Hello!";

An error! But wait — didn't we say all declarations are hoisted? Yes! Andletishoisted… but with a twist:

let and const are hoisted but left UNINITIALIZED.The variable exists in memory, but JavaScript forbids touching it until the declaration line executes.

That forbidden window — from the start of the scope until the declaration line — is theTemporal Dead Zone (TDZ):

Architecture Diagram
{
  // ═══ TDZ for 'score' STARTS ═══  console.log(score);          // ❌ ReferenceError — inside the TDZ 💀  // ═══ TDZ for 'score' ENDS ═══  let score = 100;             // ← declaration line: initialized ✅  console.log(score);          // 100 — safe zone!
}

The Complete Comparison 🏆 (Interview Gold)

KeywordHoisted?Initialized?Accessing before declaration
var✅ Yes✅ Toundefinedundefined(no error!) 😬
let✅ Yes❌ Uninitialized (TDZ)❌ ReferenceError ✅
const✅ Yes❌ Uninitialized (TDZ)❌ ReferenceError ✅

Which behavior is safer?The TDZ error, by far.var's silentundefinedlets bugs slip through;let/constscream immediately. This is yet another reason (with Lessons 4 and 10) that modern JavaScript abandonedvar— and a favorite interview follow-up:"Is let hoisted?"Yes — but the TDZ protects you from it.

🕳️ The Sneaky TDZ Trap

Watch this confusing classic:

script.js
Run Online
let brand = "Global Brand";
function printBrand() {
  console.log(brand);
  // ❌ ReferenceError! Not "Global Brand"!  let brand = "Local Brand";}

You'd expect the global to print… but thelocallet brandis hoisted within the function, putting the whole function in its TDZ — shadowing the global (Lesson 10's shadowing!)beforeit even initializes. The function's own declaration blocks access to everything namedbrandabove the line.


Function Hoisting: The Full Ride 🎢

Function Declarations — FULLY Hoisted ✅

script.js
Run Online
greet("Priya");
// ✅ "Hello, Priya!" — works BEFORE the definition!
function greet(name) {
  console.log(`Hello, ${name}! 👋`);
}

Function declarations are hoistedcompletely— nameandbody. The entire function is ready before execution begins. This is why helper functions can live at the bottom of a file while the main logic at the top calls them. Many developers use this deliberately:"main logic up top, helpers below."

Function Expressions — NOT Callable Early ❌

script.js
Run Online
greet("Priya");
// ❌ TypeError: greet is not a function
const greet = function(name) {
  console.log(`Hello, ${name}!`);
};

Theconst greetvariable is hoisted into the TDZ — but the function value doesn't exist until the assignment line. Calling early hits the dead zone.

Arrow Functions — Same Rule ❌

script.js
Run Online
greet();
// ❌ TypeError — TDZ again
const greet =() => console.log("Hi!");

And with var? The Halfway Trap 😬

script.js
Run Online
greet();
// ❌ TypeError: greet is not a function
var greet = function() {
  console.log("Hi!");
};

Why TypeError, not ReferenceError?var greetwas hoistedandinitialized toundefined— so you're callingundefined()→ "not a function." Different keyword, different error, same broken result.

The Function Hoisting Summary 🃏

StyleCallable before definition?Error type if called early
function name() {}✅ Yes — fully hoisted— (it just works!)
const/let name = function() {}❌ No (TDZ)TypeError
const/let name = () => {}❌ No (TDZ)TypeError
var name = function() {}❌ No (undefined)TypeError

🎤 The Interview Hall of Fame

Test yourself against the classics:

script.js
Run Online
// Q1: What prints?console.log(x);var x = 5;// ✅ undefined — declaration hoisted, assignment stayed put
// Q2: What prints?console.log(y);let y = 5;// ✅ ReferenceError — TDZ 💀
// Q3: What prints?hoisted();function hoisted() { console.log("Yes!"); }// ✅ "Yes!" — function declarations hoist completely
// Q4: What prints?console.log(typeof myFunc);var myFunc = function() {};// ✅ "undefined" — var hoisted as undefined; the function isn't there yet
// Q5: The boss level 🏆var x = 1;function test() {  console.log(x);  var x = 2;}test();// ✅ undefined! — the LOCAL var x hoists to the top of test(),//    shadowing the global. Effectively://    function test() { var x; console.log(x); x = 2; }

If you can explain Q5'sundefined—local declaration hoisted, assignment in place, global shadowed— you understand hoisting better than most working developers. 🎓


Best Practices: Working WITH Hoisting 🏆

Hoisting isn't a bug to fight — it's a mechanism to respect:

  1. Declare before you use—let/constat the top of their scope. The TDZ then protects you automatically.
  2. Use let/const, never var— Lesson 4's rule; hoisting weirdness is a big reason why.
  3. Define expressions before calling them— treatconst fn = …like a variable (because it is one!).
  4. Function declarations anywhere— hoisting makes them location-flexible; many devs put main logic first, helpers below. That's a style choice hoisting makes safe.
  5. When you seeundefinedunexpectedly— your first thought should now be:"Did something get used before its assignment?"🕵️

🛠️ See the Two Phases Live (Test Lab)

script.js
Run Online
function demoScope() {
  console.log("=== Phase 2 begins ===");
  console.log(typeof declaredLater);
  // "undefined" — var ghost 👻  console.log(typeof funcDeclared);      // "function" — fully hoisted! ✅
  try {
    console.log(td.z);
    // placeholder to keep structure clear  } catch (e) { /* skipped */ }
    try {
      console.log(letLater);
      // ❌ ReferenceError — TDZ!  } catch (e) {    console.log("letLater → ReferenceError (TDZ) 💀");  }
      var declaredLater = "I was a ghost";
      let letLater = "I was in the TDZ";
      function funcDeclared() {
        // hoisted entirely    return "✅";  }}
        demoScope();

Output:

script.js
Run Online
=== Phase 2 begins ===undefinedfunctionletLater → ReferenceError(TDZ) 💀

Three different hoisting behaviors, one scope, live proof. Run it yourself! 🔬


Common Beginner Mistakes (And Fixes)

❌ Misconception🔍 Reality✅ Remember
"Hoisting moves code to the top"Nothing moves — memory is prepared in the creation phaseTwo phases: create → execute
"Assignments hoist too"Only declarations hoist;= valuestays putconsole.log(x); var x = 5;→ undefined
"let/const aren't hoisted"They ARE hoisted — just uninitialized (TDZ)Interview trap question!
"All functions hoist equally"Declarations fully hoist; expressions don'tfunction f(){}≠const f = () => {}
"Hoisting is a bug"It's a designed two-phase mechanismTDZ exists toprotectyou

Quick Self-Check: Lesson 40 Quiz 🧠

  1. In one sentence: what is hoisting in JavaScript?
  2. What's the output?
    script.js
    Run Online
    console.log(a);
    var a = 10;
  3. What's the output?
    script.js
    Run Online
    console.log(b);
    let b = 10;
  4. Why does a functiondeclarationwork before its line, but a functionexpressiondoesn't?
  5. What's the output — and why?
    script.js
    Run Online
    var n = 1;
    function f() {
      console.log(n);
      var n = 2;
    }f();

(Answers: 1. JavaScript's creation phase registers declarations in memory before executing code — var initialized to undefined, let/const uninitialized (TDZ), function declarations fully · 2. undefined — the declaration hoisted, the assignment stayed · 3. ReferenceError — b is in the temporal dead zone · 4. Declarations hoist completely (name + body); expressions are variables whose function value isn't assigned until the line runs · 5. undefined — the local var n hoists within f(), shadowing the global; the console.log runs before the local assignment)


JavaScript Decision Matrix & Syntax Comparison

Understanding the mechanical differences between variable declarations and execution environments is critical for writing performant, bug-free modern JavaScript.

Variable Declarations: var vs let vs const
Feature / Propertyvar (Legacy ES5)let (Modern ES6+)const (Modern ES6+)
ScopeFunction ScopeBlock Scope ({})Block Scope ({})
Hoisting BehaviorHoisted (initialized as undefined)Hoisted (Temporal Dead Zone - ReferenceError)Hoisted (Temporal Dead Zone - ReferenceError)
Reassignable✓ Yes✓ Yes✗ No (Immutable binding)
Redeclarable in Same Scope✓ Yes (Error-prone)✗ No (SyntaxError)✗ No (SyntaxError)
Window Object BindingCreates property on windowDoes not attach to windowDoes not attach to window
Environment Decision Matrix: Browser Client-Side vs Node.js Server-Side
DimensionClient-Side (Web Browser)Server-Side (Node.js / Deno)
Global Objectwindow, document, navigatorglobal, process, globalThis
DOM & UI Manipulation✓ Full access (document.querySelector)✗ No DOM (Headless / Non-UI)
File System & OS Access✗ Blocked (Sandboxed security)✓ Full access (fs, os, child_process)
Primary FocusInteractive UI, animations, client stateREST APIs, microservices, databases, I/O streaming

Runnable JavaScript Code Example & Practical Implementation

script.js
Run Online
console.log(myVar);
// undefined (var hoisted)
var myVar = 'Hello';
sayHi();
// Works! Function definition hoisted
function sayHi() {
  console.log('Hi!');
}

Frequently Asked Questions & Technical Interview Insights

Technical Interview & Viva Questions

Frequently asked questions for frontend & full-stack roles
Q

Q: What gets hoisted first: function declarations or variable declarations?

A: Function declarations are hoisted prior to variable declarations.

Related Tools, Tutorials & Authoritative References

Recommended Interactive Tools

Authoritative Standards & Citations