Skip to content

Closures

A closure is a function that can access variables in its outer scope, even after that scope has finished executing. When you define a function inside another function, the inner function forms a closure. This lets it access and remember the outer function's variables.

Basic Closure

Here's a simple example of a closure:

js
function makeGreeter() {
    const message = "Hello";  // Variable in outer scope
    
    function greet(name) {    // Inner function
        return message + " " + name;  // Can access message
    }
    
    return greet;  // Return the inner function
}

const greet = makeGreeter();
console.log(greet("Sam"));  // "Hello Sam"
// makeGreeter finished executing, but greet still has access to message

Independent Closures

Each time we create a closure, it captures its own unique scope:

js
function makeGreeter(greeting) {
    // Each closure gets its own greeting variable
    return function(name) {
        return greeting + " " + name;
    };
}

const sayHello = makeGreeter("Hello");  // This closure captures "Hello"
const sayHi = makeGreeter("Hi");        // This closure captures "Hi"
console.log(sayHello("Sam"));  // "Hello Sam"
console.log(sayHi("Sam"));     // "Hi Sam"

Modifying Captured Variables

Closures can not only access their captured variables but also modify them:

js
function makeGreeter() {
    let greeting = "Hello";  // Initial greeting
    
    return function(name) {
        const result = greeting + " " + name;
        greeting = "Hi";     // Change greeting for next time
        return result;
    };
}

const greet = makeGreeter();
console.log(greet("Sam"));   // "Hello Sam"
console.log(greet("Alex"));  // "Hi Alex"
console.log(greet("Pat"));   // "Hi Pat"

Practical Uses

Closures provide a way to create functions that maintain their own private state:

js
function createCounter() {
    let count = 0;  // This variable is private
    
    return function() {
        count += 1;  // Can access and modify count
        return count;
    };
}

const counter = createCounter();
console.log(counter());  // 1
console.log(counter());  // 2
console.log(counter());  // 3
// console.log(count);  // Error: count is not accessible

💡 Each call to createCounter creates a new closure with its own private count variable.

External Resources