In a previous post, I was explaining how a that = this assignment was required to preserve the value of the this variable in certain scenarios. This post will focus on how to resolve them using arrow functions.

Before continuing, I strongly recommend that you read my previous post to understand why ‘that = this assignments’ were made back then and also to understand how a this variable gets it’s value.

In the previous post, I made an example using object literal declaration which made it impossible to preserve the value of this using arrow functions. So, we will discuss a different example that uses a that = this assignment to preserve the value of the this variable and later we will see how it can be replaced with arrow functions.

Consider the following example:

var name = "Global Person"; function Person() { this.name = ""; this.printName = function() { console.log(this.name); } } var perA = new Person(); perA.name = "Person A"; perA.printName() //prints Person A

In the above scenario, the new operator is used on a function when it is invoked. This is a special type of function invocation called constructor function invocation. In this type of function invocation, a new empty object is created, (let’s name it newObj ) and the function is invoked on that object, like say, newObj.Person() in this case. This means, the value of this is set to newObj for the invocation. Once, the invocation is done the newObj is returned and assigned to the perA variable.

We then set the value of the name attribute of that particular object instance, i.e, perA and invoke the printName method on that object. Everything works as expected. “Person A” is printed.

Now, lets change things up.

var printNameReference = perA.printName; printNameReference(); //prints Global Person

Here you can see that the type of function invocation is a stand alone function invocation rather than a invocation using the dot operator. This means that the value of this is set to the global object and hence “Global Person” is printed.

The takeaway here is that, though the function was defined on the object, this does not necessarily mean that the value of this is always set to that particular object. It all depends on the way the function is invoked.

Scenarios like this generally happen when you dynamically add event listeners to DOM elements, say,

myButton.addEventListener('click', obj.myFunction);

In the above statement, if myFunction depends on the value of this in it’s implementation, then you will end up getting undesired results.

So how do we fix this?

There are a couple of ways around it, one simple way used back then was to save the value of this in a local variable so that we can use it later when we need it.

var name = "Global Person"; function Person() { var self = this; this.name = ""; this.printName = function() { console.log(self.name); } } var perA = new Person(); perA.name = "Person A"; perA.printName() //prints Person A var printNameReference = perA.printName; printNameReference(); //prints "Person A"

In the above code, even though printNameReference is a standalone invocation, the printName function actually makes use of the self variable, rather than depending on the call site to get the correct value of this and hence “Person A” is printed.

What we have seen so far was before the advent of arrow functions. Arrow functions make the job much simpler as the value of the this variable for an arrow function is bound to the enclosing scope at creation time and cannot be changed. The new operator, bind , call , and apply functions have no effect on the this value of a arrow function.

So say we modify the above code as follows

var name = "Global Person"; function Person() { this.name = ""; this.printName = () => { console.log(this.name); } } var perA = new Person(); perA.name = "Person A"; perA.printName() //prints Person A var printNameReference = perA.printName; printNameReference(); //prints "Person A"

Since the printName function was defined as an arrow function rather than the traditional anonymous function, and since it is defined within the lexical scope of the function Person , the value of this is set to the surrounding lexical scope.

As mentioned earlier, the value of this for an arrow function cannot be changed at run time.

As a result even though printNameReference() is a standalone function invocation, we still end up with the correct this value, as it cannot be overridden by the invocation.