0
0
Javascriptprogramming~15 mins

What hoisting is in Javascript - Deep Dive

Choose your learning style9 modes available
Overview - What hoisting is
What is it?
Hoisting is a behavior in JavaScript where variable and function declarations are moved to the top of their containing scope before the code runs. This means you can use variables and functions before you write them in your code. However, only the declarations are hoisted, not the initial values or assignments.
Why it matters
Hoisting exists to make JavaScript code more flexible and forgiving, allowing functions and variables to be used before they appear in the code. Without hoisting, you would have to declare everything before using it, which can make code less readable and harder to organize. Understanding hoisting helps avoid confusing bugs where variables seem to exist but have unexpected values.
Where it fits
Before learning hoisting, you should understand basic JavaScript syntax, variables, and functions. After hoisting, you can learn about scopes, closures, and asynchronous JavaScript, which build on how JavaScript handles variables and functions.
Mental Model
Core Idea
JavaScript lifts all variable and function declarations to the top of their scope before running code, so they exist earlier than you see them in the code.
Think of it like...
Imagine writing a letter where you list all the people you will mention at the top before telling the story. Even if you talk about someone later, the reader already knows they exist because you introduced them upfront.
┌─────────────────────────────┐
│ JavaScript engine starts     │
│ parsing the code             │
├─────────────────────────────┤
│ Step 1: Hoisting phase       │
│ - Move declarations to top  │
│ - Variables declared, but   │
│   not assigned values yet   │
├─────────────────────────────┤
│ Step 2: Execution phase      │
│ - Run code line by line      │
│ - Use hoisted declarations  │
└─────────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding variable declarations
🤔
Concept: Variables are containers for storing data values in JavaScript.
In JavaScript, you declare variables using keywords like var, let, or const. For example: var name = 'Alice'; let age = 25; const city = 'Paris'; These variables hold values you can use later in your code.
Result
Variables store data that you can use and change (except const) in your program.
Knowing how variables are declared is essential because hoisting affects how these declarations behave before the code runs.
2
FoundationUnderstanding function declarations
🤔
Concept: Functions are blocks of code designed to perform tasks and can be called multiple times.
You can declare a function like this: function greet() { console.log('Hello!'); } greet(); // Calls the function and prints 'Hello!' Functions help organize code into reusable pieces.
Result
Functions let you run the same code whenever you want by calling their name.
Functions are also affected by hoisting, which means you can call them before their declaration in the code.
3
IntermediateHow var variables are hoisted
🤔Before reading on: do you think a var variable has its value before or after its declaration line? Commit to your answer.
Concept: Variables declared with var are hoisted with their declaration but not their assigned value.
Consider this code: console.log(x); // What happens here? var x = 5; JavaScript moves the declaration 'var x;' to the top, but the assignment '= 5' stays where it is. So, before the assignment, x exists but is undefined.
Result
The console prints 'undefined' because x exists but has no value yet.
Understanding that var declarations are hoisted but assignments are not helps explain why variables can exist but be undefined early in code.
4
IntermediateHow function declarations are hoisted
🤔Before reading on: can you call a function before its declaration in JavaScript? Yes or no? Commit to your answer.
Concept: Function declarations are fully hoisted, meaning both their name and body are moved to the top.
Example: sayHi(); // Works fine function sayHi() { console.log('Hi!'); } Because the entire function is hoisted, you can call it before it appears in the code.
Result
The console prints 'Hi!' even though the function call is before the declaration.
Knowing functions are fully hoisted explains why they can be used earlier in code, unlike variables with var.
5
IntermediateDifference between var, let, and const hoisting
🤔Before reading on: do you think let and const variables behave the same as var when hoisted? Commit to your answer.
Concept: let and const are hoisted differently; they exist in a 'temporal dead zone' until their declaration line runs.
Example: console.log(y); // ReferenceError let y = 10; Unlike var, let and const are hoisted but cannot be accessed before their declaration, causing an error if you try.
Result
The console throws a ReferenceError because y is in the temporal dead zone.
Understanding this difference prevents bugs caused by accessing let or const variables too early.
6
AdvancedHoisting with function expressions and arrow functions
🤔Before reading on: do you think function expressions are hoisted like function declarations? Commit to your answer.
Concept: Function expressions and arrow functions assigned to variables are not hoisted as functions, only their variable declarations are hoisted (if var).
Example: console.log(foo); // undefined var foo = function() { console.log('Hi'); }; foo(); // Works here The variable foo is hoisted but assigned undefined initially, so calling foo before assignment causes an error.
Result
The first console.log prints undefined; calling foo before assignment causes a TypeError.
Knowing this helps avoid errors when using function expressions or arrow functions before their assignment.
7
ExpertWhy hoisting can cause subtle bugs
🤔Before reading on: do you think hoisting can cause variables to overwrite each other unexpectedly? Commit to your answer.
Concept: Hoisting can cause unexpected behavior when variables or functions share names in the same scope or when using var inside blocks.
Example: function test() { console.log(a); // undefined var a = 1; if (true) { var a = 2; // same variable as above console.log(a); // 2 } console.log(a); // 2, not 1 } test(); Because var is function-scoped and hoisted, the inner var a overwrites the outer one, causing confusion.
Result
The console prints undefined, 2, and 2, showing the variable was overwritten unexpectedly.
Understanding hoisting's interaction with scope helps prevent bugs where variables unexpectedly change values.
Under the Hood
When JavaScript runs, it first scans the code for variable and function declarations. It sets up memory space for these declarations at the start of their scope. For variables declared with var, the space is created and initialized with undefined. For functions, the entire function code is stored. This happens before any code runs, so references to these names exist early. Assignments and initializations happen later during execution.
Why designed this way?
Hoisting was designed to allow flexible coding styles where functions and variables can be used before they appear in the code, making code organization easier. Early JavaScript engines implemented this to simplify parsing and execution. However, this design can cause confusion, so newer keywords like let and const were introduced to provide clearer behavior.
┌───────────────────────────────┐
│ JavaScript Engine Execution    │
├───────────────────────────────┤
│ 1. Creation Phase              │
│ ├─ Scan for declarations       │
│ ├─ Allocate memory             │
│ │  - var variables = undefined │
│ │  - functions = full code      │
│ └─ Setup scope environment     │
│                               │
│ 2. Execution Phase             │
│ ├─ Run code line by line       │
│ ├─ Assign values to variables  │
│ └─ Execute functions           │
└───────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does hoisting move variable assignments to the top too? Commit yes or no.
Common Belief:Hoisting moves both variable declarations and their assigned values to the top.
Tap to reveal reality
Reality:Only declarations are hoisted; assignments stay where they are in the code.
Why it matters:Believing assignments are hoisted can cause confusion when variables are undefined early, leading to bugs.
Quick: Can you call a function expression before its definition? Commit yes or no.
Common Belief:All functions, including function expressions, are hoisted fully and can be called before their definition.
Tap to reveal reality
Reality:Only function declarations are fully hoisted; function expressions are not hoisted as functions, only their variable declarations (if var) are hoisted as undefined.
Why it matters:Misunderstanding this causes runtime errors when calling function expressions too early.
Quick: Does let behave the same as var in hoisting? Commit yes or no.
Common Belief:let variables are hoisted just like var and can be accessed before declaration.
Tap to reveal reality
Reality:let variables are hoisted but cannot be accessed before their declaration due to the temporal dead zone, causing ReferenceError if accessed early.
Why it matters:Assuming let behaves like var leads to unexpected errors and confusion.
Quick: Does hoisting apply to variables declared inside blocks with var? Commit yes or no.
Common Belief:Variables declared with var inside blocks are scoped to that block and hoisted only within it.
Tap to reveal reality
Reality:var is function-scoped, not block-scoped, so variables declared inside blocks are hoisted to the function or global scope.
Why it matters:This can cause variables to overwrite each other unexpectedly, leading to bugs.
Expert Zone
1
Function declarations are hoisted before variable declarations, so if a variable and function share the same name, the function takes precedence during hoisting.
2
In strict mode, accessing let or const variables before declaration throws a ReferenceError, enforcing safer coding practices.
3
Arrow functions do not have their own 'this' binding, which affects how hoisting and execution context interact in complex scenarios.
When NOT to use
Avoid relying on hoisting for code clarity; instead, declare variables and functions before use. Use let and const instead of var to prevent hoisting-related bugs. For block-scoped variables, prefer let/const. For functions, prefer function declarations or named function expressions declared before use.
Production Patterns
In production, developers write code with declarations at the top to avoid hoisting confusion. Linters and code style guides enforce this. Modules and modern JavaScript use let/const and avoid var. Hoisting knowledge helps debug legacy code and understand JavaScript engine behavior.
Connections
Variable Scope
Hoisting works together with scope rules to determine variable visibility and lifetime.
Understanding hoisting clarifies why variables declared with var are function-scoped and how scope affects variable access.
Temporal Dead Zone
The temporal dead zone is the period during which let and const variables are hoisted but not accessible.
Knowing hoisting helps explain why accessing let/const variables early causes errors, improving debugging skills.
Compiler Behavior in Programming Languages
Hoisting is similar to how some compilers rearrange code declarations before execution.
Recognizing hoisting as a form of code preprocessing connects JavaScript behavior to general compiler design principles.
Common Pitfalls
#1Using a var variable before its assignment expecting its value.
Wrong approach:console.log(a); var a = 10;
Correct approach:var a = 10; console.log(a);
Root cause:Misunderstanding that var declarations are hoisted but assignments are not, so the variable is undefined before assignment.
#2Calling a function expression before it is assigned.
Wrong approach:foo(); var foo = function() { console.log('Hi'); };
Correct approach:var foo = function() { console.log('Hi'); }; foo();
Root cause:Believing function expressions are fully hoisted like function declarations, but only the variable declaration is hoisted as undefined.
#3Accessing let variable before declaration causing runtime error.
Wrong approach:console.log(b); let b = 5;
Correct approach:let b = 5; console.log(b);
Root cause:Not knowing about the temporal dead zone where let and const variables exist but cannot be accessed before declaration.
Key Takeaways
Hoisting moves variable and function declarations to the top of their scope before code runs, but not their assignments.
var declarations are hoisted and initialized with undefined, while let and const are hoisted but not initialized, causing a temporal dead zone.
Function declarations are fully hoisted, allowing calls before their definition, but function expressions are not fully hoisted.
Understanding hoisting helps prevent bugs related to variable initialization and function calls before declaration.
Modern JavaScript prefers let and const over var to avoid hoisting confusion and improve code clarity.