JavaScript (ES5) - this
Tags: javascript, beginners
Published: 2018-11-27 21:52:16

_This was originally posted on my site at https://martyhimmel.me on January 16, 2017. Like a number of others on dev.to, I've decided to move my technical blog posts to this site._

The `this` keyword can be a bit tricky to understand in JavaScript. Before we get too deeply into it, I should mention strict mode, as the behavior of `this` is a little different depending on if it's used in strict mode or not.

At its core, strict mode is there to enforce better coding practices in JavaScript. There are a few things it changes about the way JavaScript code is interpreted by the browser. As the scope of strict mode could easily be it's own tutorial or article (and it has been on many sites!), I'm not going to go over all the details of it here. Instead, I'd encourage you to read [Mozilla's developer docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) regarding strict mode, especially before continuing this tutorial.

## `this` in the Global Scope

`this` is a reference to an object. What object depends on the context of where `this` is called.

In the global scope, both in strict and non-strict modes, `this` is a reference to the `window` object. Anytime there's a reference to the global scope, it's actually talking about the `window` object. Consider this example:

```js
var foo = 42;
console.log(foo); // 42
console.log(window.foo); // 42
console.log(this.foo); // 42
```

Any variable or function you define in the global scope actually attaches it to the `window` object. So, when you're working in the global scope, `this` then refers to `window`. If you want to see another example of this, open the console and type `console.log(window);`, then `console.log(this);` - you'll see the same output. And if you create any variables or functions and then run either of those statements, you'll see those variables/functions in the logged object.

## `this` in an Object

This is the same for both strict and non-strict mode. As seen in the above section, the global scope is actually a top level object - the `window` object. That being said, any time `this` is called inside an object, it works exactly the same by referencing the object it's called on.

```js
var person = {
  firstName: 'John',
  lastName: 'Smith',
  fullName: function() {
    return this.firstName + ' ' + this.lastName;
  }
};
console.log(person.fullName()); // John Smith
```

In the `fullName` function, `this` is a reference to the container object - `person`. `this.firstName` could be written as `person.firstName`. Why use `this` then? Imagine you have another variable with the same name (`person`) somewhere else in your script. What does `person.firstName` refer to then? Depending on the structure of the code, it may reference the wrong `person` object. That's where `this` becomes essential - it only references the object it's being called on.

## `this` in Functions

In the above section, you already saw `this` inside of a function, but that function was wrapped in the `person` object. But what happens when you have a global function and use `this`? This is where strict mode actually matters. Let's look at the code first:

```js
var fullName = 'Jane Doe';
function getName() {
    return this.fullName;
}
```

Let's cover non-strict mode first. In non-strict mode, `this` is a reference to the closest object _in context_. In the previous section, `person` was the closest object in the context of the function.

If you remember that the global scope is actually the `window` object, then `this` in a global function becomes easier to understand. In the `fullName` example, the function is in the global scope, which means it's part of the `window` object. In turn, the closest object to the function is the `window` object, so `this` refers to the `window`. And since `fullName` is the same as `window.fullName` (because it's in the global scope), `this.fullName` inside the global function references the global variable.

Now let's look at strict mode. In strict mode, `this` is a reference to whatever object it was bound to in the execution context. What this means is there's a significant difference between `fullName` and `window.fullName`. In the former, the execution context is the function, while in the latter, the execution context is `window`.

Due to strict mode looking at the execution context rather than object context, when calling `getName()`, the function throws an `Uncaught TypeError`. The reason being `this` is `undefined` in the execution context. You can see this if you add a `console.log(this);` statement inside the function.

On the other hand, if you call `window.getName()`, the function is bound to the `window` object at execution time. In that case, the function works properly and if you log `this` inside the function, it logs the `window` object.

Let's look further into how `this` works in functions.

With a constructor type of function, `this` works just like it does in objects. We'll use this function as our basis:

```js
function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.getName = function() {
    return this.firstName + ' ' + this.lastName;
  };
}
```

Anytime you create a new object with the `Person` function, `this` is bound to that instance of the object. It works the same way in both strict and non-strict mode.

```js
var person = new Person('John', 'Smith');
console.log(person.firstName); // John
console.log(person.lastName); // Smith
console.log(person.getName()); // John Smith

var anotherPerson = new Person('Jane', 'Doe');
console.log(anotherPerson.firstName); // Jane
console.log(anotherPerson.lastName); // Doe
console.log(anotherPerson.getName()); // Jane Doe
```

Since `this` is bound to the individual instance, `person` has its own `this` reference, while `anotherPerson` has its own reference.

## `this` in Argument Functions

Things get a bit tricky when you pass a function as an argument to another function, such as in an event listener. Consider a button click listener:

```js
// Using an anonymous function
document.getElementById('myButton').addEventListener('click', function() {
  console.log(this); // logs the button element (HTML)
});

// Using a declared function
document.getElementById('myButton').addEventListener('click', myClickListener);
function myClickListener() {
  console.log(this); // logs the button element (HTML)
}
```

It doesn't matter if you create an anonymous function inline or pass a declared function, nor does it matter if you use strict or non-strict mode, the results are the same. In the above button click listener example, `this` references the object that called the function - in this case, the button.

That doesn't seem too bad, right? Let's complicate it a bit. What happens if you're passing a function that already has its own `this` reference. For example, instead of logging `this` to the console when a button is pressed, we want to log the full name of `person` (from the previous example).

```js
document.getElementById('myButton').addEventListener('click', function() {
  console.log(person.getName()); // John Smith
});
```

In that anonymous function version, it works the way we expect it to. That makes sense since we're calling the function on the object, not passing it as an argument. Let's use the method as an argument instead.

```js
document.getElementById('myButton').addEventListener('click', person.getName);
// undefined undefined
```

In this case, even though `getName` is a method of the `person` object, we're not calling the function directly on the object, but passing it as an argument. Instead of `this` referencing the `person` object, it references the button element. The button has no `firstName` or `lastName` property attached to it, so it returns `undefined`.

There's a way around that, though. JavaScript has a built in `bind` function to handle it. In it's simplest form, the `bind` function binds `this` to whatever object you pass in.

```js
document.getElementById('myButton').addEventListener('click', person.getName.bind(person));
// John Smith
```

What that says is to bind `this` to the person object when calling `person.getName` within the context of the button's event listener.

## `this` in Closures

Closures have a unique behavior when it comes to `this`. Normally, an inner function has access to the outer function's variables. That's not the case with `this`. Each function has its own version of `this`. Consider this code:

```js
var person = {
  scores: [1, 2, 3, 4],
  getScores: function() {
    console.log(this);
    this.scores.forEach(function(score) {
      console.log(this);
      // do something
    });
  }
};
person.getScores();
```

In the `getScores` method, `this` has predictable behavior - it references the `person` object (in both strict and non-strict modes). Things change once we step into the inner function inside the `forEach` loop.

The inner function doesn't have access to the object itself - only the wrapping/outer function's variables and anything in the global scope (the `window` object). Because of this behavior, you can think about the function as a stand-alone function (from the "`this` in Functions" section). In non-strict mode, `this` refers to the `window` object. In strict mode, `this` is `undefined`.

So how do we get around that? Create a variable in the outer function that's set to `this` so that variable is available to the inner function.

```js
var person = {
  scores: [1, 2, 3, 4],
  getScores: function() {
    console.log(this);
    var that = this;
    this.scores.forEach(function(score) {
      console.log(that);
      // do something
    });
  }
};
```

Now, the `that` variable is assigned to the value of `this` in the outer function - in other words, the `person` object. Using `that` anywhere in the inner function gives us the same behavior as `this` in the outer function.

Using `var that = this;` or `var self = this;` is a common practice to handle this situation. While these are both common, it might be easier to understand if you use a more succinct variable name. In this example, `var personObject = this;` makes it clear what you're referring to.