What is the meaning of ‘this’?

As a newbie to JavaScript, the concept of this has been bewildering at times. The keyword this can mean different things for ES5 functions than it does for ES6 (arrow) functions.

After three weeks of using the language, I’ve come to learn a good rule of thumb: always use arrow functions. But I was curious why there is a difference so I looked into it.

It turns out that arrow functions use what’s called lexical scoping. This means that the function always defines its this by where the function was declared. If it was declared in the global scope, this will always refer to the global scope. If it was declared within an object, this will always refer to the object.

Furthermore, if an arrow function foo is declared within another function bar, foo will define this based on what bar's this is.

ES5 functions are not this straightforward. ES5 functions define this based on what is executing them. If an ES5 function called foo is declared in the global scope but invoked within another function bar, the original function foo’s this will be the function in which it was invoked, bar. If foo is used as a callback for an event listener, its this will actually be the node on which the listener was set. The definition of this relies on the context in which the function is invoked.

This has some interesting and unsuspected consequences. Take the below example:

If we create a new instance of the object Person like this: const mike = new Person(“Mike”, “Sup?”) and invoke the function mike.saySaying(), we get the expected result of logging “Hey!” to the console.

But when we try invoking the second method, speak(), something strange happens.

The function speakSaying() doesn’t have access to the this.name property in the Person object because its this is actually the function speak(), and speak() doesn’t have a this.name property. This is a little perplexing, but never fear: arrow functions are here to save the day.

If we change the speakSaying() function to arrow notation, the problem is fixed.

Now, invoking the function on our object instance produces the expected result.

The arrow function retains the concept of this in which it was declared.

If we want to keep the function in ES5 notation, we can fix this issue instead by using the Function.prototype.bind() method. This method allows us to define the function’s this ourselves.

After we declare the function speakSaying(), we bind it to the speak() method’s this, which is the Person object, causing the speakSaying() function to behave in the same way it did using arrow notation.

This would also work if the speakSaying() function is declared outside of the Person object.

However, the bind() method will not change an arrow function’s this. This means that ES5 function notation is useful if you need control over a function’s definition of this. Most of the time, though, it’s best to stick with arrow functions.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store