DEV Community

Cover image for Closures In Javascript
angDecoder
angDecoder

Posted on

Closures In Javascript

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 :


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

Enter fullscreen mode Exit fullscreen mode

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.


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());

Enter fullscreen mode Exit fullscreen mode

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.

function add(a){
   return function(b) {
      if(b===undefined) 
         return a;
      else 
         return add(a+b);
  }
Enter fullscreen mode Exit fullscreen mode

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.


const sum = (
  function add(a,b){
    if( b===undefined ) 
      return a;

    return add.bind(null,a+b);

  }
).bind(null,0)

Enter fullscreen mode Exit fullscreen mode

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.


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

Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)