Learn JavaScript in Construct, part 8: object methods

25

Index

Features on these Courses

Stats

6,714 visits, 14,803 views

Tools

Translations

This tutorial hasn't been translated.

License

This tutorial is licensed under CC BY-NC 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

Published on 5 Nov, 2021. Last updated 16 Dec, 2021

Arrow functions and 'this'

In part 6 we covered arrow functions and mentioned briefly how this works differently with them. Let's cover the difference now.

Arrow functions don't have their own this value. Instead they take the value of this from the surrounding scope. The example below demonstrates this.

let person = {
	name: "Joe"
};

// Outside of a function, 'this' is undefined.
// The arrow function takes 'this' from the surrounding scope
// - which is here - so it is undefined.
person.arrowFunc = () => console.log(`'this' is ${this}`);

// Logs: 'this' is undefined
person.arrowFunc();

Normally you'd expect person.arrowFunc() to call arrowFunc() with this set to person. However arrow functions override that rule and use this from their outer scope, in this case setting this to undefined.

At first glance this might seem like an odd exception to the rule, but it does come in useful in practice. It's useful for using functions inside methods when you want to re-use the same value of this, in particular when using the callback pattern.

To illustrate this let's take a quick detour through a click event. Browsers provide a global document object representing the HTML document for the page. Many browser objects also have an addEventListener method to handle events. This method accepts a function that will be called by the browser when the given event happens, also known as a callback. So we can use the following code to detect whenever the user clicks their mouse anywhere in the page.

document.addEventListener("click", function ()
{
	console.log("Click event!");
});

When previewing this, click inside the preview window, and then check the browser console. You should see it log Click event! as the browser calls the function every time the "click" event happens anywhere in the page.

Now try moving this code to a method and add a reference to this. It won't work as expected, because this does not refer to the person object.

let person = {
	name: "Joe",
	
	initialize()
	{
		document.addEventListener("click", function ()
		{
			console.log(`Click event! The person's name is ${this.name}`);
		});
	}
}

// Call initialize() to add the click event listener
person.initialize();

Now when you click in the preview window, it will log Click event! The person's name is undefined, which is not what we wanted. The reason is the browser is calling the "click" event function without a reference to the person object.

One way to solve this is to take advantage of a closure, which we covered in part 6. A variable can be added to the initialize() function that remembers the value of this. Then the "click" function can refer to that variable instead.

let person = {
	name: "Joe",
	
	initialize()
	{
		// Save the value of 'this' when it refers to the right object
		let savedThis = this;
		
		document.addEventListener("click", function ()
		{
			// Refer to 'savedThis' instead of 'this'
			console.log(`Click event! The person's name is ${savedThis.name}`);
		});
	}
}

person.initialize();

It now works as expected: when we click in the page, it logs Click event! The person's name is Joe.

However we can take advantage of the fact arrow functions take the value of this from their outside scope, just like with savedThis in the example above. Then we can refer to this as normal without having to have a different variable.

let person = {
	name: "Joe",
	
	initialize()
	{
		// Use an arrow function, which remembers 'this'
		document.addEventListener("click", () =>
		{
			console.log(`Click event! The person's name is ${this.name}`);
		});
	}
}

person.initialize();

This works the same as before, correctly logging the name Joe. It demonstrates how arrow functions are useful both for their shorter syntax, and for using the value of this from the outer scope. This kind of callback pattern is very common in practice, so this feature of arrow functions remembering this is actually a useful thing to take advantage of.

  • 2 Comments

  • Order by
Want to leave a comment? Login or Register an account!