Below is a simple demonstration of closure.
The function print is nested inside the outer function printName and when printName is invoked, print is going to get invoked which will log the name that is being passed as a parameter to the outer function to the console. The actual console log is within the inner function which means that name is visible inside the inner function thus validates the concept of closure.
It is possible for the inner function to have more than 3 scope chains. Consider the example below.
In the above code snippet, the most inner function combine can see the variables of the outer function getSentence. Furthermore combine can also see the parameters of the most outer function saySentence. In terms of scope chain, the function combine has four scope chains which are its own scope, the scope of getSentence, the scope of saySentence and then lastly the global scope.
Closure can create unexpected outcomes especially for loops. Before the introduction of the let keyword, var was used for declaring variables. Let's consider the example below.
If you just look at the function, you might expect the results that are getting printed out to be 10, 11, and 12 respectively. However, the results that are printed out are all 13. What is happening here is that the closure which is the anonymous function has access to the outer function’s variables by reference, not by value.
This is because the variable i is declared with var and thus has function scope due to hoisting. The value of i is determined when functions a, b, and c are executed. Because the loop has already run its course by that time, the value of i will be the last value when the for loop ends which is 3 since 3 is equal to the length of the array. Thus the results are being printed out as 13.
There are a couple of ways to solve this issue. One of them as mentioned briefly earlier is to use let instead of var so hoisting of variable declaration is not going to interfere with the result. Inside the for loop, just replace var with let in front of i to produce the right outcome. Another way is to use anonymous closure.
Anonymous closure is a way to create anonymous functions and execute them immediately so the code inside the functions are in a closure where the right values will be captured once these functions are executed. Below is an example of using anonymous closure to capture the i value.