Understand JavaScript closures.

Learn what is closures and how closures work behind the scenes.

I have had a lot of difficulties while understanding one of the most interview-asked concepts closures. Most of the time I feel now I know closures then again found something new about it. So in this blog, I will write my way of understanding the closures.

According to MDN docs

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).

Before we start

Before diving, into the main parts, let's break down some basic JavaScript.

  • Scope
  • Lexical Scope

Scope

In JavaScript, scope tells us what variable we have access to.

  • Local Scope
  • Global Scope

Local Scope

A variable that is inside a specific part of the code is known as inside a local scope. The local scope has further two types:

  • Block Scope
  • Function Scope
Block Scope

For now, you can think block scope is anything that contains variables inside of the curly braces. e.g.

{
let name = "monu" // inside block scope
let age = "21"
}

note: we can't use a variable declared inside of block scope until its var.

Function Scope

Any variable which is inside of the function is known as inside the function scope. e.g.

function name(){
  let name = "monu" // inside function scope
  console.log(name)
}

note: we can't use a variable declared inside of function scope.

Global Scope

Any variable that is outside of the curly braces and function is known as inside of the global scope. e.g.

let name = "monu" // inside of global scope

function printName(){
console.log(name)
}

note: we can use global scope variable inside any block scope and function scope

The Lexical Scope

Now we know SCOPE. Let's understand the lexical scope first with the nesting scope.

Nesting Scope

Scope inside the scope is known as Nesting scope. In nesting scope, we can access the value which is inside the parent of the child scope.

Let us break this with an example

function outerFunction(){ //outer scope
  let name = "monu"

function innerFunction(){ // inner scope
  console.log(name)
}
  innerFunction()
}

// output : monu

as we can see that the outerfunction has the variable name but still inside the innerfunction we can access it. Why is this possible?

Here comes the lexical scope in the picture. The mechanism which helps innerfunction to have the access to variables of its lexical scope.

Lexical Scope is the space where the item is created. The item can access all the variables outside of its scope.

In the above example, you can think of what the lexical scope of the inner function is. In the following manner.

innerfunction => outerfunction => global scope

Closures

Now we know about how lexical scope works in JavaScript.

Let's understand closures with the above-given example.

In the lexical scope example, we were executing the function inside the outerfunction scope. But in this time we will return innerfunction.

1 function outerFunction(){ //outer scope
2      let name = "monu"
4
3   return function innerFunction(){ // inner scope
5       console.log(name)
6   }
7 }
8
9 let result = outerFunction()
10 result() // output : monu

And now the execution of outerFunction is completed at line number 9 and the result is stored inside the result variable.

But still somehow when we are executing the result which stored the returned function from outerFunction, Still it has access to the variables of its lexical scope although I using it outside of its lexical Scope.

How is this possible?

This is what closure is. Easy right?

You can think of closure which gives you the power to access the variables of outerfunction from the innerfunction.

That's it.

How closures works

Now we know what is closures but how it works still unclear.

Let's break this one.

To understand how closures work let's see what happened when JavaScript runs the function.

There are a few things that happened under the hood.

  • A whole new execution context created
  • All the variable inside the function is inside the local execution context
  • When the function finishes executing its local memory got deleted and the function pops out from the call stack.
  • The result of the function is stored where the function is called. e.g. global execution context, some other local execution context.

Now we know that when the function completes its execution we lost all the data inside of it. But suppose somehow we can hold the data of the function somewhere e.g. some kind of cache. How we can do this? We can do it by just returning a function from a function.

function getName(){
  let name = "Monu"
  return function (){
  console.log(name)
 }
}
let  name = getName() // return function will hold the data of getName
name() // Monu

The process of holding the data of the environment variable (memories) of function is known as closures. We can only hold the data by returning a function from the inner function.

Note: Every function creation creates a closure. Function declaration in global scope creates a closure with its lexical scope but as we know we directly access the variable of the global scope inside the function so there is no use of closure here.

Application of closures

There are many use cases of closures. These are the following

  • Higher-order functions like currying use the closures mechanism
  • We can create a function that will run once
  • We can create memoize function using closures
  • we can write private methods using closures

I will talk about the uses of closure in another blog.

Disadvantages of closures

  • The variable declared inside closure is not garbage collected
  • Sometimes it slows down the program.

Summary

  • There are two types of scopes in JavaScript Local and Global Scope.
  • Variable inside the block scope or function scope known as inside the local scope
  • Variable outside of block known as an inside the global scope
  • Scope rules give the accessibility of the variables
  • Lexical scope gives us the power to use the variable outside of the function scope.
  • Whenever a function is a return from an outer function closure is formed.
  • Closure is way a to hold the data of the function after the execution of the function is completed.

Till then Thank you and show some love to this blog.