DEV Community

Cover image for JavaScript Closures Cheatsheet
Debojyoti Saha
Debojyoti Saha

Posted on

JavaScript Closures Cheatsheet

1. What is a Closure?

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment)

2. Basic Example

function outerFunction() {
    let outerVariable = 'I am outside!';

    function innerFunction() {
        console.log(outerVariable);
    }

    return innerFunction;
}

const myFunction = outerFunction();
myFunction(); // Output: I am outside!
Enter fullscreen mode Exit fullscreen mode

3. Lexical Scoping

Closures work by capturing variables from their lexical environment.

function makeCounter() {
    let count = 0;

    return function() {
        count++;
        return count;
    }
}

const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
Enter fullscreen mode Exit fullscreen mode

4. Immediately Invoked Function Expression (IIFE)

IIFEs create closures to encapsulate variables.

const increment = (function() {
    let counter = 0;
    return function() {
        counter++;
        return counter;
    }
})();

console.log(increment()); // 1
console.log(increment()); // 2
Enter fullscreen mode Exit fullscreen mode

5. Closure with Loop (Common Pitfall)

Using var in a loop can lead to unexpected behavior due to function-level scope.

for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}
// Output: 3, 3, 3
Enter fullscreen mode Exit fullscreen mode

Solution with let:

for (let i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}
// Output: 0, 1, 2
Enter fullscreen mode Exit fullscreen mode

6. Data Privacy

Closures can be used to emulate private variables.

function createSecretHolder(secret) {
    let secretValue = secret;

    return {
        getSecret: function() {
            return secretValue;
        },
        setSecret: function(newSecret) {
            secretValue = newSecret;
        }
    };
}

const holder = createSecretHolder('mySecret');
console.log(holder.getSecret()); // 'mySecret'
holder.setSecret('newSecret');
console.log(holder.getSecret()); // 'newSecret'
Enter fullscreen mode Exit fullscreen mode

7. Partial Application

Closures can be used for partial function application.

function add(a) {
    return function(b) {
        return a + b;
    }
}

const addFive = add(5);
console.log(addFive(3)); // 8
Enter fullscreen mode Exit fullscreen mode

8. Function Factories

Closures enable function factories.

function multiplier(factor) {
    return function(number) {
        return number * factor;
    }
}

const double = multiplier(2);
console.log(double(5)); // 10

const triple = multiplier(3);
console.log(triple(5)); // 15
Enter fullscreen mode Exit fullscreen mode

9. Module Pattern

The module pattern uses closures to create public and private methods.

const Module = (function() {
    let privateVar = 'I am private';

    function privateMethod() {
        console.log(privateVar);
    }

    return {
        publicMethod: function() {
            privateMethod();
        }
    };
})();

Module.publicMethod(); // 'I am private'
Enter fullscreen mode Exit fullscreen mode

10. Handling Asynchronous Closures

function createCounter() {
    let count = 0;

    return {
        increment: function() {
            count++;
            return count;
        },
        getCount: function() {
            return count;
        }
    };
}

const asyncCounter = createCounter();

setTimeout(() => {
    asyncCounter.increment();
    console.log(asyncCounter.getCount()); // 1
}, 1000);
Enter fullscreen mode Exit fullscreen mode

11. Closures in Event Listeners

function setupButton() {
    let clickCount = 0;

    document.getElementById('myButton').addEventListener('click', function() {
        clickCount++;
        console.log(`Button clicked ${clickCount} times`);
    });
}

setupButton();
Enter fullscreen mode Exit fullscreen mode

12. Common Use Cases

  • Encapsulation: Protecting variables from being accessed or modified outside their intended context.
  • Callbacks: Passing a function as an argument to be executed later.
  • Event Handlers: Managing event-driven programming.
  • Functional Programming: Creating higher-order functions and function factories.

13. Best Practices

  • Minimize the use of closures for better memory management.
  • Be mindful of scope and lifetime of variables.
  • Use const or let instead of var to avoid common pitfalls with closures in loops.

Top comments (2)

Collapse
 
jonrandy profile image
Info Comment hidden by post author - thread only accessible via permalink
Jon Randy 🎖️ • Edited

A closure is a function that retains access to its lexical scope even when the function is executed outside that scope.

A closure is not a function. If your definition were correct then there would be no point having separate words for 'closure' and 'function' since ALL functions have this capability.

Some comments have been hidden by the post's author - find out more