Closures in JavaScript - simplified

Closures in JavaScript - simplified

One of the few challenges that beginners face while learning JavaScript is the concept of closures. Although fairly simple, closures are one of the more confusing concepts to understand, especially when one tries to implement it in a project. In this post, we'll try to understand what closures are in the simplest terms possible along with some practical examples. Let's begin!

Pre-requisites

  • Basic JavaScript

  • Functions

  • IIFE's (Immediately Invoked Function Expressions)

Before diving into closures, it's essential to have a good grasp of basic JavaScript concepts, including functions and Immediately Invoked Function Expressions (IIFE's). If you're not familiar with these topics (or even if you know them), I recommend brushing up on them before proceeding.

What are Closures?

Let's start with a non-technical analogy: Imagine a closure as a little function that carries a memory of its past. It can still use the stuff it learned from where it was born, even when it’s out exploring the world.

Now for the technical explanation: At its core, a closure is simply a function that remembers its outer scope even when the function is executed outside that scope. In other words, a closure allows a function to access variables from an enclosing function scope even after the outer function has finished executing.

Let's break this down with an example:

function outerFunction() {
  let outerVariable = "I am from outerFunction";

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

let myFunction = outerFunction();
myFunction(); // Output: "I am from outerFunction"

In this example, innerFunction is a closure. Even though outerFunction has finished executing, innerFunction still has access to the outerVariable from its lexical scope.

Practical Use Cases

Closures are commonly used in JavaScript for maintaining state, data privacy, and creating higher-order functions.

  1. Maintaining State:

     function counter() {
       let count = 0;
    
       return function() {
         return ++count;
       };
     }
    
     let incrementCounter = counter();
     console.log(incrementCounter()); // Output: 1
     console.log(incrementCounter()); // Output: 2
    

    In this example, the counter function returns a closure that increments the count variable each time it's called, effectively maintaining the state across multiple function calls.

  2. Data Privacy:

     function createPerson(name) {
       return {
         getName: function() {
           return name;
         },
         setName: function(newName) {
           name = newName;
         }
       };
     }
    
     let person = createPerson("Alice");
     console.log(person.getName()); // Output: "Alice"
     person.setName("Bob");
     console.log(person.getName()); // Output: "Bob"
    

    In this example, the createPerson function returns an object with getName and setName methods. These methods form a closure over the name variable, providing data privacy by allowing controlled access to the variable.

  3. Creating Higher-order Functions:

     function multiplier(x) {
       return function(y) {
         return x * y;
       };
     }
    
     let multiplyByTwo = multiplier(2);
     console.log(multiplyByTwo(3)); // Output: 6
    

    Here, the multiplier function returns a closure that takes a y argument and multiplies it by x, demonstrating how closures can be used to create higher-order functions.

Conclusion

Let's summarize whatever you've read above:

  • A closure is a special kind of function.

  • When you create a closure, it remembers the variables from the place where it was defined.

  • Even if you use the closure somewhere else, it still has access to those remembered variables.

If, while reading this article, you come across some terms or concepts that you're not aware of (for example "state", or "Higher-order functions"), I encourage you to look them up in short, come back, and read it again. This way you'll have a better understanding of the concepts. Happy learning!