advertisement

Scope & Closures

Master JavaScript's variable scoping rules and the powerful closure pattern that enables data privacy and function factories.

What is Scope?

Scope determines where variables are accessible in your code. It's the "visibility" of variables - which parts of your code can see and use them.

Why Scope Matters

  • Prevents variable naming conflicts
  • Controls memory usage
  • Enables data privacy
  • Makes code more predictable

Types of Scope

Global Scope

Variables declared outside any function or block. Accessible everywhere.

const globalVar = "I'm global!";

Function Scope

Variables declared inside a function. Only accessible within that function.

function fn() { var local = "I'm local"; }

Block Scope

Variables declared with let/const inside {}. Only accessible within that block.

if (true) { let block = "I'm block-scoped"; }
Scope Examples
// Global scope
const globalVar = "global";

function outer() {
    // Function scope
    var functionVar = "function-scoped";
    
    if (true) {
        // Block scope
        let blockVar = "block-scoped";
        const alsoBlock = "also block-scoped";
        var notBlock = "NOT block-scoped (var)";
    }
    
    console.log(notBlock);  // Works! var ignores block scope
    console.log(blockVar);  // ReferenceError!
}

Scope Chain

When JavaScript looks for a variable, it starts in the current scope and moves outward through parent scopes until it finds it (or reaches global scope).

Scope Chain Example
const a = "global";

function outer() {
    const b = "outer";
    
    function inner() {
        const c = "inner";
        console.log(a, b, c);  // All accessible!
        // Looks: inner scope �?outer scope �?global scope
    }
    
    inner();
}

outer();  // Output: "global outer inner"

Closures

A closure is a function that "remembers" variables from its outer scope, even after the outer function has finished executing.

Definition

A closure = Function + Its Lexical Environment

Classic Closure Example
function createCounter() {
    let count = 0;  // Private variable
    
    return function() {
        count++;
        return count;
    };
}

const counter = createCounter();
console.log(counter());  // 1
console.log(counter());  // 2
console.log(counter());  // 3
// count is "closed over" - private but persistent!

Practical Uses of Closures

Data Privacy

Create private variables that can't be accessed directly

Function Factories

Generate specialized functions with pre-configured behavior

Memoization

Cache expensive function results for reuse

Event Handlers

Maintain state between events without global variables

Function Factory Example
function createMultiplier(factor) {
    return function(number) {
        return number * factor;
    };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5));   // 10
console.log(triple(5));   // 15