Closure

·

2 min read

After a function finishes executing, the local variables of the function are no longer available.

What if we want to keep the state of the variables between multiple function calls?

That's where JavaScript closures come in.

A closure is when an inner function references variables in the outer scope, even after the outer function has finished execution.

Let's look at an example.

// This is NOT the correct way to implement Closure!
function outer() {
    let counter = 0;
    function inner() {
        counter++;
        console.log(counter);
    }
    inner();
}

outer(); // prints 1
outer(); // prints 1
outer(); // prints 1
outer(); // prints 1

If a function is called where it was defined, then each call instantiates new local variables. The counter variable is reset every time the outer() function is called.

// This is the correct way to implement Closure!
function outer() {
    let counter = 0;
    function inner() {
        counter++;
        console.log(counter);
    }
    return inner;
}

const myFunc = outer();

myFunc(); // prints 1
myFunc(); // prints 2
myFunc(); // prints 3
myFunc(); // prints 4

However, if a function is called outside of where it was defined, then the instance of inner() saves the local variables of the outer() function.

In this case, myFunc() is a reference to the instance of the function inner() that is created when outer() is run.

And every time myFunc() is called, the variable counter is available.

So how is this possible? This is because the instance of inner() maintains a reference to the lexical environment. The lexical environment is the data that was available when the function is defined.

Closure can be useful when you want your functions to save variables, somewhat like private variables in Object Oriented Programming!