# Closure in js

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**

```javascript
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**

```javascript
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**

```javascript
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:

```javascript
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.
