Closure in js

Table of contents

No heading

No headings in the article.

Closure in JavaScript refers to the ability of a function to access and remember the values of variables declared outside of its own scope, even after the outer function has returned.

When a function is defined within another function, the inner function has access to all the variables and parameters of the outer function, even after the outer function has finished executing. This means that the inner function can continue to access and modify those variables even when it is invoked later on, outside the outer function.

This concept is particularly useful for creating private variables and functions within an object, where the variables and functions are inaccessible from outside the object but can still be used by other methods within the object.

In simpler terms, closure allows a function to remember and use variables and functions from its parent function even after the parent function has finished running.

Here are a couple of examples of closure.

Example 1: Creating a private variable using closure

function counter() {
  let count = 0;
  return function() {
    count++;
    console.log(count);
  }
}

const increment = counter();
increment(); // 1
increment(); // 2
increment(); // 3

In this example, the counter function returns another function that increments a private variable count each time it is called. The count variable is not accessible from outside the counter function, but the returned function can still access and modify it thanks to closure.

Example 2: Creating a function factory using closure

function createMultiplier(multiplier) {
  return function(num) {
    return num * multiplier;
  }
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

In this example, the createMultiplier function returns another function that multiplies its argument by the multiplier parameter passed to createMultiplier. By returning a function, createMultiplier can be used to create different multiplier functions with different values of multiplier. Each of these functions has access to the multiplier value even after createMultiplier has returned, thanks to closure.

Example 3: Creating an event listener using closure

function addEvent(element, eventType, handler) {
  element.addEventListener(eventType, function(event) {
    handler(event);
  });
}

const button = document.querySelector('button');
addEvent(button, 'click', function(event) {
  console.log('Button clicked!');
});

In this example, the addEvent function takes an element, an event type, and a handler function and adds an event listener to the element that calls the handler function when the event occurs. The handler function has access to the handler parameter even after addEvent has returned, thanks to closure. This allows the handler function to perform some action when the event occurs, such as logging a message to the console in this case.

Here's a practical React example that uses closure:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  function increment() {
    setCount(count + 1);
  }

  function decrement() {
    setCount(count - 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

export default Counter;

In this example, we have a Counter component that displays a count and two buttons to increment and decrement the count. The useState hook is used to create a state variable count and a function setCount to update it.

The increment and decrement functions are defined inside the Counter component and use closure to access the count and setCount variables. When the user clicks the increment or decrement button, the corresponding function is called and updates the count state variable.

The use of closure here is important because it allows the increment and decrement functions to have access to the count state variable even after the Counter component has rendered and returned. This ensures that the count is always updated correctly when the user clicks the buttons.