The scope is the set of variables accessible in a block of code.
We have 2 types of scopes:

  • global
  • local

The global scope is the set of variables accessible in the script.
The local scope is the set of variables accessible in a block of code.

const age = 20;
function sayHello() {
    const name = 'John';
    console.log(`Hello ${name}, you are ${age} years old`);
}

// console.log(`Hello ${name}, you are ${age} years old`); // error, name is not accessible here

Differences between var, let and const

1. VAR - Function scoped

function testVar() {
    if (true) {
        var x = 1;
    }
    console.log(x); // 1 - accessible because var is function-scoped
}

2. LET - Block scoped

function testLet() {
    if (true) {
        let y = 1;
    }
    // console.log(y); // error - y is not accessible here
}

3. CONST - Block scoped, non-reassignable

function testConst() {
    const z = 1;
    // z = 2; // error - const cannot be reassigned
}

Hoisting

Hoisting with var

console.log(hoistedVar); // undefined (no error)
var hoistedVar = "I am hoisted";

Hoisting with let/const

// console.log(hoistedLet); // error - ReferenceError
let hoistedLet = "I am not accessible before declaration";

Redeclaration

var a = 1;
var a = 2; // OK with var

let b = 1;
// let b = 2; // error with let

Practical examples of scopes

Global scope

var globalVar = "I am global";
let globalLet = "Me too";
const globalConst = "Me too";

function scopeExample() {
    // Function scope
    var functionVar = "I am in the function";
    let functionLet = "Me too";
    const functionConst = "Me too";
    
    if (true) {
        // Block scope
        var blockVar = "I am accessible everywhere in the function";
        let blockLet = "I am only accessible in this block";
        const blockConst = "Me too";
        
        console.log(globalVar, functionVar, blockVar); // All accessible
        console.log(blockLet, blockConst); // Accessible in the block
    }
    
    console.log(blockVar); // Accessible because var is function-scoped
    // console.log(blockLet); // error - not accessible outside the block
    // console.log(blockConst); // error - not accessible outside the block
}

Loops and closures

console.log("=== Example with loops ===");

// With var - classic problem
for (var i = 0; i < 3; i++) {
    setTimeout(() => console.log("var:", i), 100); // displays 3, 3, 3
}

// With let - expected behavior
for (let j = 0; j < 3; j++) {
    setTimeout(() => console.log("let:", j), 200); // displays 0, 1, 2
}

Temporal Dead Zone

function temporalDeadZone() {
    console.log("Start of the function");
    // console.log(tempLet); // ReferenceError - Temporal Dead Zone
    let tempLet = "Now I am accessible";
    console.log(tempLet);
}

Objects and const

const obj = { name: "John" };
obj.name = "Jane"; // OK - we modify the content, not the reference
obj.age = 25; // OK
// obj = {}; // error - we cannot reassign

const arr = [1, 2, 3];
arr.push(4); // OK - we modify the content
// arr = []; // error - we cannot reassign