JavaScript Closure

                       JavaScript Closure

1.The scope

The scope is a space where we can access variables. Now you know two interesting things:

  • Scopes can be nested

  • The variables of the outer scope are accessible inside the inner scope

 

2. The lexical scope

The lexical scoping means that inside the inner function (child) scope you can access variables of outer function (Parent) scopes.

3. The closure

The closure is a function that accesses its lexical scope even executed outside of its lexical scope.

You create a function (Parent) within another function, then the inner (child) function is closure

The closure has three scope chains

  1. Own scope where variables defined between its curly brackets

  2. Outer function’s variables

  3. Global variables

For example:

Example 1:

function multiply(a) {

               return function executeMultiply(b) {

                                  return a * b;

                     }

}

const double = multiply(2);

double(3); // => 6

double(5); // => 10

const triple = multiply(3);

triple(4); // => 12

The function executeMultiply() is closure function. multiply is a curried function that returns another function.

Currying, an important concept of functional programming, is also possible thanks to closures.

Example 2: It is consider as most important question.

for (var i = 0; i < 3; i++) {

                     setTimeout(function log() {

                     console.log(i); // Output 3 3 3

              }, i*1000);

}

This is because var has global scoped and the value of i becomes 3 after the for loop completes its execution. for loop is synchronous function and execute faster than setTimeout() which is asynchronous function. Then, the callback functions of setTimeout() print the value of i which is now 3.

Solution:

 solution 1(using let)

for (let i = 0; i < 3; i++) {

               setTimeout(function log() {

              console.log(i);

        }, i*1000);

}

(solution 2)using closures (immediately invoked function)

for (var i = 0; i < 3; i++) {

                     ((ind) => {

                     setTimeout(function log() {

               console.log(ind);

       }, ind*1000);

})(i);

}

Example 3: Access variables from the outer scope

let countClicks = 0;

button.addEventListener(‘click’, function clickHandler() {

        countClicks++;

});

clickHandler accesses the variable countClicks from the outer scope.

Example 4: Doesn’t access any variables from the outer scope

const result = (function immediate(number) {

           const message = `number is: ${number}`;

           return message;

     })(100);

immediate doesn’t access any variables from the outer scope.

Example 5: Access variables from the outer scope

setTimeout(function delayedReload() {

             location.reload();

}, 1000);

     delayedReloadaccesses the global variable location from the global scope

Example 6:

function createIncrement() {

           let count = 0;

           function increment() {

                     count++;

      }

let message = `Count is ${count}`;

           function myfunction() {

                   console.log(message);

      }

        return [increment, myfunction];

}

const [increment, log] = createIncrement();

increment();

increment();

increment();

myfunction (); // count is 0

Count is 0 is logged to console.

increment() function has been called 3 times, effectively incrementing count to value 3.

message variable exists within the scope of createIncrement() function. Its initial value is ‘Count is 0’. However, even if count variable has been incremented a few times, message variable always holds ‘Count is 0’.

log() function is a closure that captures message variable from the createIncrement() scope. console.log(message) logs ‘Count is 0’ to console.

Conclusion

The scope rules the accessibility of variables. There can be a function or a block scope.

The lexical scope allows a function scope to access statically the variables from the outer scopes.

Finally, a closure is a function that captures variables from its lexical scope. In simple words, the closure remembers the variables from the place where it is defined, no matter where it is executed.

Closures allow event handlers, callbacks to capture variables. They’re used in functional programming.