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.

Understanding JavaScript’s ‘this’

JavaScript functions are objects and so can have properties. When a function executes it gets a this property. The value of this will refer to the object that called the function.

Global scope

When running code in the browser, window is the global object. The value of this will be the window object when this is referenced in the global scope.

We can see in the code that window and this are interchangeable.

Function scope

When referencing this within a function, the value of this is not set until the function is called.

Here this is referenced within a function but because the function is called in the global scope the value of this is the window object.

The same applies when printName() is called.

When using strict mode the value of this in global functions will be undefined.

Object method

Remember that the value of this is not set until the function is called.

Here this refers to myObject because it called printThis().

myObject calls printName() so the value of this is myObject and this.name will evaluate to ‘My Object’.

Here we define the function printName() independent of myObject and attached a reference to the myObject property printName. Again, myObject calls printName so the value of this is myObject and this.name evaluates to ‘My Object’.

This example has nested objects and we call printName() by first going through outerObject to call innerObject.printName(). Here the value of this is innerObject because it is the direct caller of printName(). It does not matter that we started by calling outerObject.

Prototypes

Here myObject calls both printName() and printThis() which means that the value of this for both is myObject. myObject does not have a property named name, it is inherited from the prototype. Note that this does not affect the value of this. this is still set to the object that called the function.

Constructor

We use the function MyConstructor as a constructor using the new keyword. In this case this will point at the new object being constructed, myObject.

Closures

In this example this inside the anonymous function no longer refers to myObject so this.name will be undefined.

One solution is to store a reference to this in a variable and use the variable instead. Later we will see how this can be fixed using bind.

forEach can be passed a second parameter which allows us to specify what should be used for this.

Now this.name will evaluate to ‘My Object’ because we have passed in this as the second parameter to forEach.

Here again this inside innerFunction no longer refers to myObject because myObject is not the direct caller of innerFunction().

We can fix it by storing a reference to this in a variable. Now it prints ‘My Object’ as expected.

This behaves exactly as the last example. We just defined outerFunction outside of myObject.

Event handler

this within the anonymous function does not refer to myObject, it will be set to the element the event fired from.

Again to fix just store a reference to this in a variable.

Here this refers to the element on which the listener is attached so this.id evaluates to ‘btn’.

this does not refer to the element because this is located within a function. It actually refers to the global window object.

eval

At the point where eval is called this refers to myObject. However because someFunction() is called not on some object but on the global scope, this refers to window.

Here eval is not calling a function which references this, hence this refers to myObject. Remember, at the point where eval is called this refers to myObject.

Method assigned to a variable

Here this refers to myObject as expected.

Here however printThisVar is assigned a reference to the printThis method in myObject. this will refer to window when invoking the function using printThisVar() as it is called in the global scope.

Now we copied a reference of the function to myOtherObject.printThis and we can see that this now refers to myOtherObject.

call and apply

All functions inherit from Function.prototype. Two of the methods available here are call and apply. Calling either call or apply with no parameters means that this will be bound to the window object.

firstName or lastName are not defined in the global scope so we get undefined.

If you have a function that references this, then we can use call or apply to specify what object this refers to. Calling call or apply on a function executes the function.

Here we have specified that this should refer to the person object.

call and apply do the same thing, the difference is in how we pass arguments to the function.

For call the first argument is the object to bind to this followed by a comma separated list of values which will be used as the arguments for the function.

For apply the second argument is an array of values which will be used as the arguments for the function.

bind

Another method in Function.prototype is bind which was introduced in ECMAScript 5. Note that calling bind does not execute the function. It returns a reference to a new function in which this is bound to the specified object.

Calling bind we can bind the value of this to person. Now every time we call print() the value of this will be the person object.

We can also pass parameters to bind. These will then be used as the arguments in the newly created function.

Revisiting the forEach example we had earlier in the closures section we can use bind to set the value of this. Calling .bind(myObject) would give the same result.

Arrow functions

With ES6 we can use arrow functions.

Here this is set lexically because we used the arrow function token =>. this will be set to the enclosing code’s context, which here is myObject. The same applies for the Car example.

Again in this example this refers to myObject because of the arrow function. The arrow function gets its value of this from the enclosing context. Note that arrow functions are always anonymous which is why we assigned it here to the variable innerFunction.