Closure in javascript Complete concept
Tags: webdev, javascript, beginners, programming
Published: 2023-06-05 21:24:40

**In JavaScript, a closure is a combination of a function and the lexical environment in which that function was declared. It allows the function to access variables from its outer scope even after the outer function has finished executing.**

To understand closures better, let's look at an example:

```javascript
function outerFunction() {
  var outerVariable = 'I am from the outer function';

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

  return innerFunction;
}

var closure = outerFunction();
closure(); // Output: I am from the outer function
```

In this example, `outerFunction` is the outer function that contains `innerFunction`. Inside `innerFunction`, we are accessing the `outerVariable` from the outer scope of `outerFunction`. Even though `outerFunction` has finished executing and its execution context is gone, `innerFunction` still has access to the `outerVariable`. This is possible because of the closure.

Closures are created when an inner function is defined inside an outer function and the inner function is returned or passed as a reference to another function or stored in a variable. In our example, we return `innerFunction` from `outerFunction` and assign it to the `closure` variable. The returned `innerFunction` still retains access to the variables of its outer scope, forming a closure.

**Few more examples to understand closures in JavaScript:**

Example 1: Counter Function

```javascript
function createCounter() {
  let count = 0;

  return function() {
    count++;
    console.log(count);
  };
}

const counter = createCounter();
counter(); // Output: 1
counter(); // Output: 2
counter(); // Output: 3
```

In this example, the `createCounter` function creates a closure. It declares a `count` variable and returns an inner function. The inner function has access to the `count` variable from its outer scope. Each time the inner function is invoked, it increments the `count` and logs the updated value to the console. The output shows how the inner function, due to the closure, can access and modify the `count` variable even after the `createCounter` function has finished executing.

Example 2: Private Variable

```javascript
function createPerson(name) {
  let privateName = name;

  return {
    getName: function() {
      return privateName;
    },
    setName: function(newName) {
      privateName = newName;
    }
  };
}

const person = createPerson('John');
console.log(person.getName()); // Output: John
person.setName('Jane');
console.log(person.getName()); // Output: Jane
```

In this example, the `createPerson` function creates a closure that encapsulates a private variable `privateName`. It returns an object with two methods: `getName` and `setName`. The `getName` method accesses and returns the private `privateName`, while the `setName` method modifies the private variable. The closure ensures that the `privateName` variable is not accessible from outside the `createPerson` function, providing data privacy.

Example 3: Emulating Private Methods

```javascript
var Counter = (function() {
  let count = 0;

  function increment() {
    count++;
    console.log(count);
  }

  function decrement() {
    count--;
    console.log(count);
  }

  return {
    increment: increment,
    decrement: decrement
  };
})();

Counter.increment(); // Output: 1
Counter.increment(); // Output: 2
Counter.decrement(); // Output: 1
```

In this example, an immediately invoked function expression (IIFE) is used to create a closure. The IIFE defines private variables `count` and private functions `increment` and `decrement`. It returns an object with the public methods `increment` and `decrement`. The closure allows the public methods to access and modify the private `count` variable, while keeping it hidden from the global scope.

These examples demonstrate different use cases of closures in JavaScript, such as maintaining private variables, creating function factories, and encapsulating data. Closures provide a powerful mechanism for achieving data privacy and creating modular and reusable code.


**Closures are useful in many scenarios, including:**

Data Privacy:
Closures can be used to create private variables and functions. By encapsulating variables within an outer function and exposing only necessary functionality through inner functions, you can control access to data and provide a level of privacy.

Function Factories:
Closures allow you to create functions dynamically with different configurations. By defining an outer function that takes certain parameters and returns an inner function, you can create specialized functions tailored to specific needs.

Callbacks:
Closures are often used with callbacks to capture and maintain the state of variables. The inner function, being a closure, retains access to the variables from the outer scope, even when the callback is invoked later.