A closure has three scope chains:
- Access to its own variables.
- Access to variables within the outer function.
- Access to global variables.
A closure has access to the parameters of the outer function. It cannot call the outer function’s arguments object, but calling the outer function’s parameters directly is possible.
Some of this is easier to understand with the help of an example.
In the above code, we have two functions, outer and inner. The inner function is a closure declared inside the outer function. The inner function is returning a variable that is declared in the outer function and the outer function returns the inner function. Pay attention to the following line of code.
var get_inner = outer();
Here, we are done with the execution of the outer function. The entire body of the inner function is returned and stored in the get_inner variable. Let’s take a look at what will happen in the next line.
Here we are calling the inner function that is stored in the get_inner variable. This will print the value of the variable val, that was declared inside the outer function. This happens because the variable val is in the scope of the inner function.
As mentioned earlier, the inner function also has access to the parameters of the outer function. In order to better understand this, let’s look at another example.
In this example we are setting the variable get_inner to the outer function passing an argument of 100. The outer function passes back the inner function in its return statement. We now have access to the inner function via get_inner and can pass it an argument of 50. When we call get_inner (50), we are executing the outer function with an argument of 100, which in turn returns inner, where we pass in 50. These values are summed and yield a result of 150.
var get_inner = outer(100);
The execution of the outer function ends here. But still, when we use get_inner to call the inner function, The inner function returns the correct sum of the arguments. This happens because the closures can access the parameters of the outer function.
We can also store anonymous functions at every index of an array.
The for loop runs from i=0 to i=4, and at each index, we are storing the value of i at that point. Each index has a function, that is why used the following line of code to print the value returned for that function in the console.
As the index specified here is 0, you might imagine the the value stored in it to be 0, however that is not the case. Here the value is 5. Similarly, all the indexes of this array will 5. This happens because the closures do not remember the value, they only store the reference of the variable. At the end of the for loop, the value of i is 5, thus storing the value at each index of the array.
The following shows us how to get around this problem.
Here we are passing a different argument every time the inner function is called. Now, at the 0th index, value is 0 and at the 1st index, value is 1. Similarly, all other indexes have different values.
Hopefully this example helps better articulate that closures only store the reference, not the value.
To recap, remember the following three rules about the closures.
- Closures have access to variables of the outer function even after the outer function returns.
- Closures have access to the parameters of the outer function.
- Closures store the reference of variables of the outer function.
Image Credits: Photo by Peter G on Unsplash.