Closures in JavaScript

Closures in JavaScript

Introduction

Closures are created when the function is defined, allowing the nested child function to access the parent's variables even when the parent function has finished its execution. Now let's learn Closures with examples.

Examples

  • From the below example, we can learn how we can emulate private variables and functions with the help of closures.

      // global scope
      let x = 1;
      const parentFunction = () => {
        let myValue = 2;
       // accessing the global variable x inside the parentFunction
        console.log(x);
        console.log(myValue);
    
        const childFunction = () => {
          // nested child function can access the variables of parentFunction
          // and global variables as well
          console.log((x += 5));
          console.log((myValue += 1));
        };
        return childFunction;
      };
    
      const parentResult = parentFunction();
      // we are able to access the parent Variables even though parent function has finished executing.
      parentResult(); 
      parentResult();
      parentResult();
      // we will not get 1 as we are able to access the global variable and we are changing it's value within childFunction
      console.log(x);
    
  • Example of closure with IIFE.

      const withdrawMoney = ((money) => {
        let amount = money;
        console.log(`Initial amount: ${amount}`);
        return () => {
          amount -= 1000;
          if (amount > 0) {
            console.log(`Money withdrawn 1000, money left ${amount}`);
          }
          if (amount <= 0) {
            console.log("can't withdraw money");
          }
        };
      })(3000);
      // everytime we are running withdrawMoney function amount is getting
      // deducted by 1000
      withdrawMoney();
      withdrawMoney();
      withdrawMoney();
    
  • A real-life example of closures: let's say we want to change the background colour of the web page based on the button clicked.

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <title>Document</title>
        </head>
    
        <body>
          <button id="orange">orange</button>
          <button id="red">red</button>
          <button id="green">green</button>
          <script>
            function clickHandler(color) {
              return () => {
                document.body.style.backgroundColor = color;
              };
            }
            document.getElementById("orange").onclick = clickHandler("orange");
            document.getElementById("green").onclick = clickHandler("green");
            document.getElementById("red").onclick = clickHandler("red");
          </script>
        </body>
      </html>
    

Disadvantages

Memory Usage: Closures can lead to more memory usage as the entire scope chain will exist in the memory until all the closure references are removed. This means that the variables which would have been removed by the garbage collector will exist in the memory as long as the closure exists.

function outerFunction(value) {
    let arr = new Array(100000).fill(value);
    return () => {
        console.log(value);
    }
}
const innerfunction = outerFunction(10)
// array created above will stay in the memory as long as the closure exists

Conclusion

JavaScript closure is a incredibly useful feature which allows nested function to access the parent variable even, when the parent function has finished it's execution. It allows to emulate private variables, maintaining state in an application, and facilitating event handling in a web browser. However, closures have their disadvantages as well, this can lead to increased memory usage as entire scope chain will exist in the memory until all the closure references are removed. Understanding closures and their advantages and disadvantages is essential for effective JavaScript programming.