JavaScript Closures

All JavaScript functions are in fact closures. A closure is a combination of the function and the environment in which it was created. This allows functions to access variables outside of their immediate lexical scope.

Nested functions

The closure allows the inner function to not only access its own locally defined variables, but also variables defined in the outer function. This is why the inner function can log the value of outerVar even though this variable is not defined locally.

The inner function also has access to the outer functions arguments so innerFunction can log the value of outerFunctionArg. The inner function cannot however access the outer functions arguments object.

This example shows something very interesting about closures. Here we do not call the inner function immediately. The outer function now returns a reference to the inner function which we store in functionVariable. When we execute this function we can see that it still prints the value stored in outerVar. The closure allows the inner function to access the outer functions variable even though the outer function has already been executed. When a function in JavaScript executes, it has access to its parent scope even after the parent function returns.

In this example there are 2 closures, one for logValue and another for setValue. Note that if one function changes the value of outerVar then this change is reflected when we call the other function. This shows an important point about closures, they store a reference to the outer functions variables and not just the value.

Closures in a loop

When we call the outer function, we loop 3 times adding an anonymous function to the myFunctions array. At the end we call these 3 functions which when called prints the value of i. You might expect it to print 0, 1 and 2 but as discussed above each function stores a reference to i and not the value. So by the time we call each function the loop is finished and the value of i is 3.

The issue can be fixed using an IIFE (Immediately Invoked Function Expression). So we immediately execute the function passing the loop variable i in as a parameter. This simply returns another anonymous function which we place in myFunctions and when called at the end prints the value of loopIndex. This works because when passing in a primitive variable into a function, it is passed by value and not by reference

This works because of the same reason as above. The makeFunction variable loopIndex is passed by value.

Counter example

This example uses a closure to implement a simple counter. The function makeCounter returns a function that when called increments the value of count by 1. After we create the counter the only way to modify the count is by calling counter. This makes the code much more secure because any other code cannot access the variable count.
Look what happens when we call makeCounter a second time and call anotherCounter. It will not log 4, 5, 6. This is because each call to makeCounter creates a new closure with its own count variable.

Private data

Closures can be used to emulate private data in JavaScript.

When we create a new Car object a closure is created and the function getMake continues to hold a reference to the variable make. Note that no other code can modify the variable make. We can try using myCar.make = ‘Nissan’ but myCar.getMake will still return ‘Ford’. myCar.make = will just add a new property to the Car object. This has no effect on the variable make which was defined within the Car function.

Leave a Reply

Your email address will not be published. Required fields are marked *