Closures in JS ๐Ÿ’™๐Ÿ’ฏ

ยท

4 min read

Closures in JS ๐Ÿ’™๐Ÿ’ฏ

If you're beginner , intermediate or senior developer it doesn't matter what is your level of experience but I bet you that there is 99% chance you've heard about this beautiful thing known as closures even you might've used it in your journey a lot of times ,I've used it butI didn't knew what was it until I actually came to know about it ,if you still don't know What really closures are?

In this article I will clarify each and everything about the closures.

What are closures?โ™โ—€๏ธ

`Functions which are bundled along with their lexical environment & scope and has reference to all their variables are known as Closures.`

Now first you need to understand what is the meaning of lexical environment & Scope here?

Everytime a program executes or a execution context get's created a lexical environment get's created which is used to keep track of the mapping of identifiers to specific variables via references.โ™

In Javascript, Scope determines the accessibility of variables , objects and functions from different parts of the code.๐Ÿ†Ž

Let's understand the closure with an help of an example:-

const myName = "Prabadhya";

function printMyName () {
  console.log(myName);
}

printMyName();

// Output:- Prabadhya

In the above example there is an function named printMyName which logs the output to the console which is stored in an variable which is not inside that particular function. So whenver javascript executes that line it tries to find that particular variable inside the memory of the printMyName function execution context but it doesn't find it so with the reference of parent lexical enviroment in this case global execution context it looks for that variable.

For better understanding of the execution contexts & memory creation I would highly recommend you all to check out my this article on Javascript & execution context.๐Ÿ’ฏ;

Let's understand it with another example as sometimes it may seem a little bit confusing at first :-

function printSomething () {
  let a = 5;
  function innerFunction () {
    console.log(a);
  }
  return innerFunction;
}

let c = printSomething(); 

console.log(c); // OutPut:- [Function: InnerFunction]

c(); // OutPut:- 5

In the above example we've two function a parent function and child function nested inside parent function. In parent function we've declared an variable we're trying to access that variable inside a child function. but instead of invoking the child function in the parent function itself we're returning that particular function.

After the function declaration we're invoking the function and storing the value inside another variable c. When we log output to the console we get the InnerFunction as an output because we've not invoked the function as yet.

But if you know the concept of concept of call stack & execution context you must be aware that whenver we return something from an function that function itself get's vanished from the call stack.

And if we notice when we invoke InnerFunction via c variable we'll see the output as 5 but how it is possible because whenever we return something from function whole execution context of that function get's destroyed so if the execution context of function printSomething has already been vanished then how come we're still able to access the variable a which was inside the parent function. It is possible because of lexical environment which has stored an reference of variables so that we can access them even after the execution context gets vanished.

Some common use cases of closures:-

  1. Private methods & variables:- In javascript , we can use private variables and methods using closures. For example:-
// Define the closure

var carPrice = function(initialPrice) {
var price = initialPrice;

    // Define private variables for the closure

    return {
    getPrice: function() {
        return console.log(price);
    },
    incPrice: function(amount) {
        price += amount;
        console.log(price);
    },
    decPrice: function(amount) {
        price -= amount;
        console.log(price);
    }
    }
}

var Price = rentPrice(8000);

// Access the private methods
Price.incPrice(2000);
Price.decPrice(1500);
Price.getPrice();

In the above example, the carPrice() function returns an object with three methods: getPrice(), incPrice(), and decPrice(). These three methods has access to the private variable price. However, the code outside its scope cannot directly access this variable. Hence, we can mimic object oriented programming in JavaScript.

2. Currying functions in Javascript:- It is a technique in functional programming, transformation of the function of multiple arguments into several functions of a single argument in sequence.

    function calculateVolume(length) {
        return function (breadth) {
            return function (height) {
                return length * breadth * height;
            }
        }
    }
    console.log(calculateVolume(4)(5)(6));

In the above example we're invoking the function calculateVolume() after invoking it would return another function with some code , it will get repeated till the end. We'll be able to access all the variables with the help of closures.

To know more about memory creation phase & how javascript works behind the bars! I would highly recommend to check out my previous article.

Well this is for today and thanks a lot for reading! Hope this helps you out!๐Ÿ’™

Do Read , Share and Code ๐Ÿ’ป

Ping me any time in case of any doubts & clarifications โ˜บ๏ธ

ย