Closures in JavaScirpt
Tags: javascript, webdev, beginners, opensource
Published: 2022-05-19 07:27:21

Hello, Everyone! Hope You all are doing well.

### Table of Contents

- What is Scope?
- What is Global, Block and Function scope?
- What is Lexical Scope?
- What is Closures?

In this Blog, I'll be writing about Closures, one of the confusing topic in JavaScript. And I'm sure that every JavaScript programmer encountered this name while learning JavaScript Language.



To understand Closures in better way. Here's is prerequisites to know. But don't worry if you don't know these concepts, I'm also writing about these Topics Such as Scope, Block scope, Function scope, Lexical Scope as mentioned above. 

Let's Start with Scope.

### Scope

The simple meaning of Scope is accessibility of variable from where is defined in JavaScript program.

Let's Understand with example.

```
 let a = "JavaScript";
 console.log(a); // JavaScirpt
```
In the above example, It can be easily accessible. That's ok
But If we declare a variable inside a if block.

```
if (true) {
  let a = 'JavaScript';
}

console.log(a); //  ReferenceError: a is not defined
```
The above example will throw an ReferenceError: a is not defined, Because, if code block created scope with variable that only accessible inside that block only.

### Global Scope

If The variable declared outside of any other scope, and that variable can be access to any other scope.

```
var a = 5;
var b = 5;

function sum() {
  if (true) {
    const sum = a + b;
    console.log(sum); // 10
  }
}
sum();
```

In the above example, I declare two variable a, b and assign a value 5. The global variable accessed inside other scope, That's why it logs sum = 10

### Block Scope

When ES6 Introduced, Two new keyword were introduced to declare variable in JavaScirpt let and const, Both are block scope keyword. That can be only access inside that block only.

```
if (true) {
  const message = 'Hello JavaScript';
  console.log(message); // 'Hello JavaScript'
}
console.log(message); // ReferenceError
```
In the first log, It prints Hello JavaScript, because we are accessing inside that block but if we try to access outside of block it will throw an ReferenceError.

Note:- The code block for, while also create block scope.

Note: - var is not block scope.

```
if (true) {
  var message = 'Hello JavaScript';
}
console.log(message); 'Hello JavaScript'

```
In case of var keyword, if {} code block does not create a scope. That's why we're accessed message variable outside of the if block.

### Function Scope

A JavaScript functions create scope with all variables (let, const, and var) that are only accessible inside that function body.

```
function sum() {
  var a = 5;
  let b = 5;
  const c = 5;
}
sum();

console.log(a, b, c); // ReferenceError: a is not defined

```

### Lexical Scope

Let's start with an example

```
let myName = 'Pritam';

function one() {
  let age = 15;

  function two() {
    let address = 'Hazaribagh';

    let bio = `My name is ${myName}. and age is ${age}, and Address is ${address}`;

    console.log(bio); // My name is Pritam. and age is 15, and Address is Hazaribagh
    
  }

  two();
}

one();

```

In the Above Example

The function two() can access of it's Parent scopes variables, 
also can access variable of global scope. But How? How a function scope has access of it's outer function scope. Let's know about it.

> The answer is Because of Lexical scope / Lexical Environment

In the concept of Lexical scope, inner function has access of outer function's scopes.

But How it works? , How it remembers?

In JavaScript, Whenever a function created, It make reference of it's lexical variable due to an internal hidden property 
[[Environment]].

Note: All function has [[Environment]] property.

### Closures

A Closures is the combination of function bundle together with reference of It's lexical environment.

OR

A Closures allows you access of lexical scope even outside of it's lexical scope.

Note: - Every time Closures form when function created.

Let's Understand with an example.

```
function outerFunc() {
  let outerVar = 'I am Developer!';
  function innerFunc() {
    console.log(outerVar); // => logs "I am outside!"
  }
  innerFunc();
}

outerFunc();
```
In the above example, due to lexical scope, innerFunc() has access of It's lexical variable. That we know very well.

Now let's make changes on program, innerFunc() invoked to be outside of outerFunc() scope or lexical scope. I mean, in other function.

```
function outerFunc() {
  let outerVar = 'I am Developer!';
  function innerFunc() {
    console.log(outerVar); // => logs "I am outside!"
  }
 return innerFunc
}

function newFunc() {
  const myInnerFunc = outerFunc();
  myInnerFunc();
}
 newFunc()

```
In this case innerFunc has still access of its lexical scope variable (outerVar), even executed outside the scope of outerFunc(). This is case, closure comes into picture. Due to closure the innerFunc remembers it's lexical scope variable from the place where it is defined. No matter, the innerFunc invoked outside of the scope.

I hope this will give you an basic understanding of Closures.

#### References:

- https://dmitripavlutin.com/simple-explanation-of-javascript-closures/

- https://stackoverflow.com/questions/51748127/what-is-the-javascript-environment-property

Thank you for reading.