DEV Community

Cover image for Understanding Scope, Hoisting, and Closures like a Pro!
Rafsan Jany Ratul
Rafsan Jany Ratul

Posted on

Understanding Scope, Hoisting, and Closures like a Pro!

🔹 What is Scope?

Scope defines the accessibility of variables in your code.

Simply put:

Scope decides where in your code a variable can be used.

In JavaScript, every variable has a “boundary.” Outside this boundary, the variable is unavailable.

Why is Scope important?

  • Prevent variable conflicts
  • Manage memory efficiently
  • Make code predictable

Main types of Scope:

Global Scope → accessible from anywhere
Function Scope → accessible only within a function
Block Scope → accessible within {} (using let or const)
Lexical Scope → determined by the code’s written structure

🔹 Scope Example

let person = [1,2,3,4,5]; // global scope

function total(num1, num2) {
    const result = num1 + num2; // function scope

    if(true) {
        var result1 = num1 * num2; // function scope (var)
    }

    console.log(result1); // accessible
    console.log(person);  // global access
}

total(10, 20);

console.log(result); // ❌ Error, function scope

Enter fullscreen mode Exit fullscreen mode

Takeaways:

  • result is limited to the function scope, so it cannot be accessed outside the function
  • result1 is accessible inside the function not because of hoisting, but because var is function-scoped (it ignores block scope)
  • person can be accessed inside the function because it is declared in the global scope, and global variables are accessible from anywhere
  • JavaScript follows a scope chain, meaning it first looks for variables in the local scope, and if not found, it checks the outer (global) scope
  • Block scope refers to any code inside {} — such as if, else, for, or while blocks — where let and const are limited to that block only
  • A function also creates its own scope, and blocks inside functions can act as block scope when using let and const
  • var, let, and const have different scoping rules, so choosing the right one is important for predictable behavior

🔹 What is Hoisting?

Hoisting is JavaScript’s behavior where variable and function declarations are moved to memory at the beginning of the execution phase.

In other words:

Before your code runs, JS prepares memory for all declared variables and functions.

Important points:

var → hoisted and initialized as undefined
let / const → hoisted but not initialized (they stay in the Temporal Dead Zone)
Function declarations → fully hoisted

Common misconception:

Some think hoisting literally “moves code to the top,” but technically, it’s a memory preparation process.

🔹 Hoisting Example

console.log(a); // undefined
var a = 10;

Enter fullscreen mode Exit fullscreen mode

Internally, JavaScript interprets it as:

var a;
console.log(a); // undefined
a = 10;

Enter fullscreen mode Exit fullscreen mode

Using let or const:

console.log(b); // ❌ ReferenceError
let b = 10;

Enter fullscreen mode Exit fullscreen mode

This happens because let/const are hoisted but not initialized, creating the Temporal Dead Zone (TDZ).


🔹 What are Closures?

A closure is when a function “remembers” variables from its outer scope even after the outer function has finished executing.

Simply:

Function + its surrounding environment = Closure

Why closures are useful:

Maintain private data

Keep state between function calls

Widely used in real-world JS (event handlers, React hooks, etc.) 

🔹 Closure Example

function total() {
    let counter = 0;

    return function() {
        counter++;
        console.log(counter);
    }
}

Usage:


const result1 = total();

result1(); // 1
result1(); // 2

const result2 = total();

result2(); // 1
result1(); // 3

Enter fullscreen mode Exit fullscreen mode

Key points:

counter is not global

The inner function remembers its value

Each call to total() creates a new memory instance


🔹 Lexical Scope (The backbone of closures)


function outer() {
    let a = 10;

    return function inner() {
        console.log(a);
    }
}

Enter fullscreen mode Exit fullscreen mode

The inner function is declared inside the outer function

Therefore, it can access variable a

This is lexical scope, which allows closures to work
How These Concepts Connect
Scope → defines where a variable lives
Lexical Scope → defines what variables a function can access based on the written code
Closure → allows functions to “remember” variables from outer scopes
All three work together in JavaScript!

Summary

Scope → variable boundaries
Hoisting → memory preparation before execution
Lexical Scope → determines access based on code structure
Closure → functions remember outer data

Final Thought

Many unexpected behaviors in JavaScript happen because these concepts are unclear.

Once Scope, Hoisting, Lexical Scope, and Closures are understood, JavaScript becomes predictable and much easier to work with
#webdevelopment #frontend #closure #hoisting #scope #lexicalscope #learntocode

Top comments (0)