DEV Community

Cover image for πŸ“š Understanding Closures in JavaScript: A Complete Guide
Artem Turlenko
Artem Turlenko

Posted on

πŸ“š Understanding Closures in JavaScript: A Complete Guide

Closures are one of the most powerful and sometimes confusing concepts in JavaScript. They are frequently asked about in interviews and are essential for writing efficient, modular, and secure code. In this post, we’ll break down what closures are, how they work, and practical use cases for them.


πŸ” What is a Closure?

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

Example:

function outerFunction(outerVariable) {
  return function innerFunction(innerVariable) {
    console.log(`Outer: ${outerVariable}, Inner: ${innerVariable}`);
  };
}

const newFunction = outerFunction("Hello");
newFunction("World");
Enter fullscreen mode Exit fullscreen mode

Output:

Outer: Hello, Inner: World
Enter fullscreen mode Exit fullscreen mode

In this example:

  • innerFunction retains access to outerVariable even after outerFunction has finished executing.
  • This behavior is what we call a closure.

πŸ”„ How Closures Work

Closures work because of lexical scoping. When a function is defined, it remembers the variables in its surrounding scope. Even if the outer function is no longer active in the execution stack, the inner function keeps a reference to those variables.

JavaScript manages closures using the execution context and the scope chain. The inner function doesn’t just have access to its own local variables, but also variables from its parent function and the global scope.


⚑ Practical Use Cases of Closures

1️⃣ Data Privacy (Encapsulation)

Closures allow creating private variables, preventing direct access from outside.

function counter() {
  let count = 0;
  return {
    increment: function () { count++; console.log(count); },
    decrement: function () { count--; console.log(count); },
  };
}

const myCounter = counter();
myCounter.increment(); // 1
myCounter.increment(); // 2
myCounter.decrement(); // 1
Enter fullscreen mode Exit fullscreen mode

Here, count is private and cannot be accessed directly.


2️⃣ Function Factories

Closures allow functions to be dynamically created based on an input value.

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

const double = multiplier(2);
console.log(double(5)); // 10
Enter fullscreen mode Exit fullscreen mode

This is useful for currying and functional programming.


3️⃣ Event Listeners with State

Closures help maintain state in event handlers.

function attachEventListener() {
  let count = 0;
  document.getElementById("myButton").addEventListener("click", function () {
    count++;
    console.log(`Button clicked ${count} times`);
  });
}
attachEventListener();
Enter fullscreen mode Exit fullscreen mode

Each time the button is clicked, the event listener retains access to count.


4️⃣ Memoization (Performance Optimization)

Closures help cache results and improve performance.

function memoizedAdd() {
  let cache = {};
  return function (num) {
    if (num in cache) {
      console.log("Fetching from cache");
      return cache[num];
    } else {
      console.log("Calculating result");
      cache[num] = num + 10;
      return cache[num];
    }
  };
}

const add = memoizedAdd();
console.log(add(5)); // Calculating result β†’ 15
console.log(add(5)); // Fetching from cache β†’ 15
Enter fullscreen mode Exit fullscreen mode

Closures store previously computed values, reducing redundant calculations.


🎯 Key Takeaways

  • Closures allow functions to retain access to their outer scope even after execution.
  • They are created automatically when functions are returned from other functions.
  • Useful for data encapsulation, function factories, event handling, and performance optimizations.

Closures might seem tricky at first, but once you understand their behavior, they become an incredibly powerful tool in JavaScript development.

πŸ’¬ Have you used closures in your projects? Share your experiences in the comments! πŸš€

Top comments (0)