DEV Community

Mohana Naga Venkat Sayempu
Mohana Naga Venkat Sayempu

Posted on

Javascript Closures

It's is one of the most important concepts in javascript. It is a widely discussed yet confusing concept.

Let's look at an example first.

function OuterFunction() {

    var outerVariable = 1;

    function InnerFunction() {
        alert(outerVariable);
    }

    InnerFunction();
}

In above example, we have a InnerFunction() which is defined inside OuterFunction() and inside the InnerFunction() we are accessing the variable that declared in OuterFunction().

We can define closure as a function inside a function that has access to its parent parameters and local variables even after the outer function is returned. (Note: Inner function can't access the arguments object of outer function)

In a simple way, Every closure has three scopes

  • Local Scope (Own Scope)
  • Outer Function Scope
  • Global Scope

Let's see another example to understand the above-mentioned behavior.

let globalVar = 'This is from global scope';
function getCounter() {
    let counter = 0;

    function IncreaseCounter() {
        const localVar = 'This is from local scope';
        console.log(globalVar); // accessing the global scope variable
        console.log(localVar); // accessing the local or own scope variable
        return counter += 1; // accessing the outer function scope variable
    };

    return IncreaseCounter;
}
let counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
alert(counter()); // 4

First we invoke the getCounter() function which returned an inner function IncreaseCounter() . Inside that function we are accessing the local, outer and global scope variables. Each time we invoke this function, we are increasing the counter by 1 and returning that counter. Here the important point to notice is the value of counter is persistent across different function calls and it's not initialized. Technically, we can say that outer function variables are private, no body can access from outside but we can access them inside the innerfunctions.

So we can emulate the native way of defining private variables and private methods with help closures in javascript.

In the following example, we use the concept of closures to defined the public functions that can access the private functions.

var counter = (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }

  return {
    increment: function() {
      changeBy(1);
    },

    decrement: function() {
      changeBy(-1);
    },

    value: function() {
      return privateCounter;
    }
  };
})();

console.log(counter.value());  // 0.

counter.increment();
counter.increment();
console.log(counter.value());  // 2.

counter.decrement();
console.log(counter.value());  // 1.

In the above example we are using an anonymous function, which is executed as soon as it has been defined (known as IIFE) which returns an object literal. Inside this function (lexical environment), we have defined privateCounter and changeBy() which are not accessible from outside. But we are accessing this lexical environment variables and functions inside the closures. (Thanks to javascript lexical scoping).

I hope it helps to get rid of some confusion.

Any fool can write code that a computer can understand.
Good programmers write code that humans can understand.
– Martin Fowler

I am always open to suggestions and accept mistakes. So please leave a comment whatever you feel 🤗

Top comments (0)