3 Techniques for Maintaining Your Sanity Using "This" in JavaScript
Tags: beginners, javascript
Published: 2019-07-17 14:56:13

---
title: 3 Techniques for Maintaining Your Sanity Using "This" in JavaScript
published: true
tags: Beginner,JavaScript
canonical_url: https://carlanderson.xyz/3-techniques-for-sanity-with-javascript-this/
cover_image: https://images.unsplash.com/photo-1507652955-f3dcef5a3be5?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ
---

Of JavaScript's many confusing aspects, the keyword `this` can be one of the most complicated -- Here's a joke about the troublesome keyword:

{% twitter 578925947245633536 %}

`this` is _frustrating._ Every time you think you have it, another weird case shows up - it should be _simple,_ so why does it never seem to work how you want it to?

# Why "this" is confusing

In other programming languages, `this` _always_ refers to the current instance of an object. It's a very consistent keyword which will only ever hold two values: the current object, or nothing.

In JavaScript, `this` refers to what is known as the _execution context_. In practical contexts, this is _deceptively similar_ to other languages version of `this`, but contains a fundament difference: the execution context is different based on _how_ a function is called_._

This means that JavaScript's version of `this` may have different values depending on how you called the function.

``` javascript
class Foo {
	text = "string";

	trigger() {
		// Because of how the function is being called, `this` can have
		// several different values
		this.text = this.text + "a";
	}

	brokenTrigger() {
		// `this` will refer to the current object, so it will act as we expect
		this.trigger();

		// setTimeout resets `this` to the global context object - in web
		// browsers, it is the Window object
		setTimeout(this.trigger, 500);

		// When we refer to the function directly (without the object)
		// `this` refers to the global context object (window)
		const unboundFunction = this.trigger;
		unboundFunction();

		// Event listeners replace "this" with the target element 
		// `this` will refer to the clicked ".triggerButton"
		let button = document.querySelector(".triggerButton");
		button.addEventListener('click', this.trigger);
	}
}

```

# How to use `this` safely

When you see all the ways that `this` can go wrong, it seems like the easiest option is to throw your hands in the air, become a hermit and start a small potato farm.

In practice, `this` tends to be far less problematic than these examples make it appear. Most of the weird behaviours of `this` are easy to avoid by restricting your use of `this` to object functions, where it is the most consistent

As I said in the intro, using `this` with an object is _almost always_ going to refer the object instance, but you do have to watch for two major exceptions:

1. `setTimeout`
2. `addEventListener`

In these cases, we have several techniques at our disposal to control the value of `this`, and to make sure that it works how we want.

## Technique 1: Use Fat Arrow Functions

Fat Arrow Functions, aside from being a quick way of declaring functions, differ slightly from other function declarations in that they won't allow anything to overwrite `this`. Instead, it keeps the value from where the function is declared (its lexical scope).

What this means is that we can use them as wrappers, or directly as event listener function calls to preserve our `this` reference.

```javascript
class Foo {
	listen() {
		// `this` still refers to Foo
		document.querySelector('.class').addEventListener('click', (e) => {
			this.handler(e); 
			// or
			this.val = 1;
		});
	}

	handler(e) {
		this.val = 1;
	}
}

```

## Technique 2:  Assign `this` to a variable

Before ES6, a popular pattern was to copy the value of `this` when we knew it referred to our object and used the new variable instead.

```javascript
var foo = {
	listen: function() {
		// These are both common names for our new `this`
		var that = this;
		var self = this;

		document.querySelector('.class').addEventListener('click', function() {
			self.val = 1;
		});
	}
}

```

## Technique 3: Explicitly set `this` with `Function.bind`

Functions come with several tools to set the value of `this` explicitly so you can guarantee the value of `this`.

- `Function.bind`
- `Function.apply`
- `Function.call`

In practice, `Function.bind` is the most useful of the three, since it doesn't immediately call the function, instead returning a new version with a pre-set `this`, and any parameters you pass - you can use this new function directly in `setTimeout` or `addEventListener` function and keep your value of `this`.

```javascript
class Foo {
	listen() {
		// The first paramter of `bind` is the new `this` value
		document.querySelector('.class').addEventListener('click', this.handleEvent.bind(this));
	}

	handleEvent() {
		this.val = 1;
	}
}

```

## Bonus Technique: Use Strict Mode

[JavaScript's Strict Mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) slightly changes the behaviour of `this`. Instead of implicitly setting `this` to the global context outsides of objects, it causes it to be `undefined` instead.

In practical terms, this is a fairly minor change, but it prevents several incorrect usages of `this`, and cause a would-be-hidden bug to throw an error instead:

```javascript
'use strict';
let obj = {
	update(val) {
		// Normally this will create an `x` property on the global object and
		// continue running, but in strict mode this will throw an error
		this.x = val;
	}
}

// Breaking the reference to `obj` causes `this` to be undefined instead
// of referring to the global object
let func = obj.update;
func();

```

## Don't overcomplicate it

If you regularly read my blog, you'll know this is basically my slogan.

There's no denying that `this` is _strange,_ but that doesn't mean that you need to worry about all the edge cases that it presents - More often than not, they don't come up.

I've been a Web Developer for coming on eight years now, and I learned some new edge cases about `this` when preparing this post that I have never encountered before.

If you're interested in learning more about JavaScript, you can check out [this guide to closures](https://dev.to/canderson93/javascript-closures-and-how-they-work-51bk), or read this article about [what you need to know to start learning a front-end framework](https://dev.to/canderson93/when-to-start-learning-a-front-end-framework-9hk).

-------------

[Having a hard time learning JavaScript? Sign up to my newsletter for articles like this straight to your inbox](https://pages.convertkit.com/9f030a68c9/cd303b3d7b).