JavaScript Interview Prep
JS Engine & Execution

Hoisting

Why You Can Use Variables Before You Declare Them

Scenario

console.log(x) before var x = 10 prints undefined. The same pattern with let x = 10 throws a ReferenceError. Why?

The answer is hoisting - and almost every tutorial explains it wrong. Nothing physically moves to the top of your file. The JS engine simply allocates memory for declarations during the Creation Phase, BEFORE executing a single line of code.

Function declarations get fully stored (body and all), which is why you can call them before they appear. var gets initialized to undefined. let and const get hoisted but locked in the Temporal Dead Zone.


What Hoisting Really Is

Hoisting is JavaScript's behavior of moving declarations (not assignments) to the top of their scope during the Creation Phase.

But here's the important part: nothing physically moves. The JS engine just allocates memory for declarations before executing any code.

What Gets Hoisted and How?

DeclarationHoisted?Initial Value
var x = 5Yesundefined
let x = 5Yes (but in TDZ)uninitialized
const x = 5Yes (but in TDZ)uninitialized
function greet() {}YesFull function body
var greet = function() {}Yes (var only)undefined
var greet = () => {}Yes (var only)undefined

Code Example - Variable Hoisting

console.log(a); // undefined  (not ReferenceError!)
console.log(b); // ReferenceError: Cannot access 'b' before initialization
console.log(c); // ReferenceError: Cannot access 'c' before initialization

var a = 10;
let b = 20;
const c = 30;

What the engine sees (conceptually):

var a = undefined; // hoisted with default value
// let b -> exists in memory but in TDZ (no default)
// const c -> exists in memory but in TDZ (no default)

console.log(a); // undefined
console.log(b); // ReferenceError (TDZ)
console.log(c); // ReferenceError (TDZ)

a = 10;
b = 20;
c = 30;

Code Example - Function Hoisting

// This works! Function declarations are fully hoisted
sayHello(); // "Hello!"

function sayHello() {
    console.log("Hello!");
}

// This BREAKS! Function expressions are NOT fully hoisted
sayBye(); // TypeError: sayBye is not a function

var sayBye = function () {
    console.log("Bye!");
};

Why does sayBye fail? Because var sayBye is hoisted as undefined. Calling undefined() throws a TypeError.

Tricky Example - Functions vs Variables

var myFunc = "hello";

function myFunc() {
    return "world";
}

console.log(typeof myFunc); // "string"

Why? During creation phase, both are hoisted. But in the execution phase, var myFunc = "hello" reassigns it to the string. Function declarations are hoisted first, then variable assignments overwrite them.


Common Mistakes

  • Saying "hoisting physically moves declarations to the top" - it doesn't; memory is allocated in a separate phase, nothing in your source file actually moves.
  • Thinking let and const are NOT hoisted - they are, they're just kept in the TDZ until their declaration line is reached.
  • Calling a function assigned to a var before its assignment line and expecting it to work - only function declarations (the function foo() {} form) are fully hoisted; function expressions (var foo = function() {}) leave foo as undefined until the assignment runs.

Interview Questions

Q: What is hoisting in JavaScript?

Hoisting is the engine's Creation-Phase behavior of allocating memory for declarations before executing any code. var is initialized to undefined, let/const are left uninitialized in the TDZ, and function declarations are stored with their full body.

Q: Are let and const hoisted?

Yes, they are hoisted - but they're placed in the Temporal Dead Zone (TDZ) from the start of the block until the declaration line. Accessing them before declaration throws a ReferenceError, not undefined like var.

Q: What's the difference between hoisting of function declarations vs function expressions?

Function declarations (function foo() {}) are hoisted with their entire body, so they're callable before the line they appear on. Function expressions (var foo = function() {}) only hoist the var binding as undefined; calling foo() before the assignment throws TypeError: foo is not a function.

Q: What will console.log(x) output if var x = 5 is declared later?

undefined. The var x declaration is hoisted and initialized to undefined, but the assignment x = 5 stays in its original position.

Q: Does hoisting physically move code?

No. It's a conceptual description of what happens in the Creation Phase - memory is allocated for declarations, but the source text itself is unchanged.


Learn More

On this page