JavaScript Closures Cheatsheet

debojyoti

Debojyoti Saha

Posted on May 24, 2024

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.
đź’– đź’Ş đź™… đźš©
debojyoti
Debojyoti Saha

Posted on May 24, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related