09

Scope and Closures

Chapter 9 • Intermediate

45 min

Scope and Closures

Understanding scope and closures is crucial for writing effective JavaScript code. Scope determines where variables can be accessed, and closures allow functions to "remember" their lexical environment.

Scope

Scope refers to the visibility and accessibility of variables in different parts of your code.

Global Scope

Variables declared outside any function are in global scope:

javascript.js
let globalVar = 'I am global';

function example() {
    console.log(globalVar); // Can access global variables
}

Function Scope

Variables declared inside a function are only accessible within that function:

javascript.js
function example() {
    let localVar = 'I am local';
    console.log(localVar); // Works
}

console.log(localVar); // Error: localVar is not defined

Block Scope (let and const)

Variables declared with let and const are block-scoped:

javascript.js
if (true) {
    let blockVar = 'I am block-scoped';
    const anotherBlockVar = 'Me too';
}

console.log(blockVar); // Error: blockVar is not defined

Closures

A closure is a function that has access to variables in its outer (enclosing) scope even after the outer function has returned.

Basic Closure Example

javascript.js
function outerFunction(x) {
    // Outer function's variable
    let outerVariable = x;
    
    // Inner function (closure)
    function innerFunction(y) {
        return outerVariable + y;
    }
    
    return innerFunction;
}

let closure = outerFunction(10);
console.log(closure(5)); // 15

Practical Closure Example

javascript.js
function createCounter() {
    let count = 0;
    
    return {
        increment: function() {
            count++;
            return count;
        },
        decrement: function() {
            count--;
            return count;
        },
        getCount: function() {
            return count;
        }
    };
}

let counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2

The this Keyword

The this keyword refers to the object that is executing the current function. Its value depends on how the function is called.

this in Different Contexts

javascript.js
let person = {
    name: 'John',
    greet: function() {
        console.log('Hello, I am ' + this.name);
    }
};

person.greet(); // 'Hello, I am John'

let greetFunction = person.greet;
greetFunction(); // 'Hello, I am undefined' (in strict mode)

Binding this

javascript.js
let person = {
    name: 'John',
    greet: function() {
        console.log('Hello, I am ' + this.name);
    }
};

let boundGreet = person.greet.bind(person);
boundGreet(); // 'Hello, I am John'

Hands-on Examples

Scope Example

let globalVar = 'Global variable';

function outerFunction() {
    let outerVar = 'Outer variable';
    
    function innerFunction() {
        let innerVar = 'Inner variable';
        
        console.log('Inner can access:', innerVar);
        console.log('Inner can access:', outerVar);
        console.log('Inner can access:', globalVar);
    }
    
    innerFunction();
    
    console.log('Outer can access:', outerVar);
    console.log('Outer can access:', globalVar);
    // console.log(innerVar); // Error: innerVar is not defined
}

outerFunction();
console.log('Global can access:', globalVar);

Inner functions can access variables from outer scopes, but outer functions cannot access variables from inner scopes.