Closures In Javascript
Tags: discuss, node, javascript, tutorial
Published: 2024-03-24 06:47:40

## 1. What is Closure?

**Closure -->** Closure is the combination of function bundled along with its lexical environment is called "closure".

Let us understand closure using example : 

```js

function outer(){
   function inner(){
      console.log(a);
   }

   var a = 10;
   
   // returning reference of inner() function
   return inner;
}

// 'inn' variable has reference of 
// 'inner' function declared inside 'outer' function
const inn = outer();

inn(); // OUTPUT : 10

// how could inn() function can access variable 'a'
// in 'outer' function scope?

// This is because 'inner' function forms closure
// with the 'outer' function ,i.e., it remembers
// lexical environment at it's declaration

```

There are various advantages of closures, we will discuss them one by one -
- Modular Design Pattern
- Currying 
- Data Hiding and Encapsulation

## 2. Modular Design Pattern

It is a design pattern used in Javascript to encapsulate and organise code. It creates modular and reusable pieces of code. 

It can be created using ES6 modules, CommonJS modules or closure. Here, we will see only the closure implementation of modules.

Modules help organize code into logical units, making it easier to manage dependencies, isolate functionality, and scale applications.

```js

const myModule = (function(){
  var a = 10;
  function privateFun(){
    console.log(a);
  }

  function publicFun(){
    console.log(a);
  }

  // those value return from this IIFE
  // are treated as *public*
  // and rest are *private*
  return {
    publicFun,
    b : 20
  }
})();


console.log(myModule.b);
console.log(myModule.publicFun());

```

## 3. Currying in JavaScript

It is a technique to change the function with multiple arguments into sequence of functions with single arguments.

For example :- to add 3 numbers we would pass arguments like **sum(a,b,c)** but in currying we would create functions that would only take 1 or 0 arguments. So, our function would look like **sum(a)(b)(c)()**.

For summing 4 numbers, normally we would need to create new function but with currying we can use the same function **sum(a)(b)(c)(d)()**. Now, let us create this currying function.

### a. Currying with recursion
Here, we use recursion to create currying function. **add()** function has one parameter **a** and returns another function which in turns has a parameter **b**.

```js
function add(a){
   return function(b) {
      if(b===undefined) 
         return a;
      else 
         return add(a+b);
  }
```

Let us try to visualise this currying with example, **sum(a)(b)()**. So, when we call **sum(a)** it returns a function. Now, we have passed **b** to the returned function like **sum(a)(b)**, but this also returns a function. At last, we don't pass any arguments and the inner function only returns value( because b===undefined ) and not the function.

Try to visualise this on your own with the help of pen and paper for three variables.

### b. Currying with .bind() method

**.bind()** method binds a function with a object. It has one parameter, which takes an object to be binded. The other parameter passed to the function are treated as default arguments for the binded function.

```js

const sum = (
  function add(a,b){
    if( b===undefined ) 
      return a;
   
    return add.bind(null,a+b);
  
  }
).bind(null,0)

```

## 4. Data Hiding and Encapsulation 

**Data hiding** is about hiding the internal state of an object from the outside world, typically by marking certain attributes or methods as private or protected.

**Encapsulation** is the bundling of data (attributes) and methods (functions) that operate on that data into a single unit (class), and providing controlled access to them through well-defined interfaces (public methods).

Both concepts aim to improve security, maintainability, and modularity by controlling access to data and implementation details in object-oriented programming.

Let us, create a counter function to see data hiding and encapsulation in action. 

```js

function counter(){
   let count = 0;
   return {
      reset     : ()=>count=0;
      increment : ()=>count++,
      decrement : ()=>count--,
      value     : ()=>val,
   }
}

```

Calling the counter function, it returns a object using which we can use counter. But, we can't directly manipulate the **count** variable inside the **counter()** functions.

## 5. Disadvantages of Closures

Although, closures are amazing over using this could lead to serious problems like :-

a. Over Consumption of memory
b. Memory Leak
c. Freeze Browser