Understanding Closures in JavaScript
Tags: javascript, closures, webdev, codenewbie
Published: 2021-09-17 09:22:36

The callbacks, event handlers, higher-order functions can access outer scope variables thanks to closures. They are important in functional programming and are often asked in coding interviews.

Closures are difficult to grasp at the beginning. If you haven't reached the *"Aha!"* moment in understanding closures, I hope this article will benefit you.

## Scope
In order to understand closures, you must have a very good understanding of scopes.

> The scope is the context in which values and expressions are visible or can be referenced.

There are 3 types of variable scopes:

1. Global scope

2. Local scope

3. Block scope (introduced in ES6)

## Global Variables

Any variable that is declared *outside a function* has a global scope.

A global variable can be accessed by all **functions** and **scripts** in a document.

```js
var fruit = "mango";
// fruit can be accessed here

function myFunc() {
    // fruit can be accessed here as well
    alert(fruit);
}
```

Also, any variable that is initialized or has been assigned a value *inside a function* without being declared first will be **global**.

```js
myFunc(); // call the function first

document.getElementByID("fruit").innerHTML = "My favorite fruit is " + fruit;
// fruit can be accessed here

function myFunc() {
    fruit = "mangoes";
    alert(fruit);
    // fruit can be used here too
}
```

## Local Variables
Any variable that is declared *inside a function* has a **local** scope.

A local variable can be only accessed by the **function** where it was declared.

```js
// fruit can NOT be used here
document.getElementByID("fruit").innerHTML = "My favorite fruit is " + fruit;

function myFunc() {
    var fruit = "mangoes";
    alert(fruit);
    // fruit can be used here
}
```

> Note:- Changes made to a variable in the global scope takes effect inside the local scope as well

> However, changes made inside the local scope don't affect the global scope.

Similar to the local scope is the **Block** scope.

A block is any part of the code enclosed within `{` and `}`.

Variables declared using the `let` keyword are accessible within the block in which it is declared.

> Note:- Variables declared with the `var` keyword can NOT have block scope.

## Scope Nesting

Let’s play a bit more with scopes, and nest one scope into another. For example, the function `innerFunc()` is nested inside an outer function `outerFunc()`.

```js
function outerFunc() {
    // Outer scope
    let outerVar = "I'm outside";

    function innerFunc() {
        // Inner scope
        console.log(outerVar);
    }

    innerFunc();
}
```

Can you access the variable `outerVar` of `outerFunc()` from within `innerFunc()` scope?

Indeed. Try it yourself and find out.

Now you know two interesting things:

1. Scopes can be nested.

2. The variables of the outer scope are accessible inside the inner scope.

## The Lexical Scope

How does JavaScript understand that `outerVar` inside `innerFunc()` corresponds to the variable `outerVar` of `outerFunc()`?

JavaScript implements a scoping mechanism named **lexical scoping** (or static scoping).

Lexical scoping means that the accessibility of variables is determined by the position of the variables inside the nested scopes.

It’s called lexical (or static) because the engine determines the nesting of scopes at the lexing (*aka* tokenizing) time just by looking at the JavaScript source code, *without executing it*.

## The Closure

Let’s make a change: `innerFunc()` to be invoked outside of its lexical scope (outside of `outerFunc()`).

Would `innerFunc()` still be able to access `outerVar`? Let's see.

```js
function outerFunc() {
    let outerVar = "I'm outside";

    function innerFunc() {
        console.log(outerVar); // logs "I'm outside"
    }

    return innerFunc();
}

const myInnerFunc = outerFunc();
myInnerFunc();
```

`innerFunc()` still has access to `outerVar` from its lexical scope, even after being executed *outside of its lexical scope*.

In other words, `innerFunc()` remembers the variable `outerVar` from its lexical scope.


So, `innerFunc()` is a closure because it *closes over* the variable `outerVar` from its lexical scope.


> The closure is a function that has access to its lexical scope when executed **outside** of its lexical scope.


A rule of thumb to identify a closure:

If inside a function you see a variable not defined inside that function, most likely that function is a closure because that particular variable is *captured*.

Thanks for reading 🙏

More articles on JavaScript soon.

---

I write daily [Twitter](https://twitter.com/theShounakDas) threads on web development concepts, resources, and tips.