JavaScript; what's the meaning of `this`?
Tags: javascript, this, self, programming
Published: 2019-03-13 17:45:37

---
title: JavaScript; what's the meaning of `this`?
published: true
description: 
tags: javascript, this, self, programming
cover_image: 
---
![wtf mate](https://media.giphy.com/media/yDBjbceDHdt6M/giphy.gif)
Alright JavaScript, what the hell. We were cool. Now, I just don't know anymore. I was hanging out with Ruby for the past couple months and I got used to how consistent and sensible `self` is. Now I'm back and things are...weird.

What I'm struggling with most is whether or not JavaScript's implementation of `this` is a necessary evil with a first-class function language, or just another bad idea that we're stuck with. 

I'm going to condense for you some thoughts gleaned from [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this), [Kyle Simpson](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch1.md) and the [ECMA 2020 Spec](https://tc39.github.io/ecma262/). (just for fun, search for "this" in the Spec 😂)

For those that aren't already frustrated by `this`, let's get you on board the "wtf, JavaScript" train. `this` *should* allow us to write functions with an reference to the owning object without having to hardcode the name of the object.
```javascript
function Person(name) {
    this.name = name;
    this.printName = function() { console.log(this.name); };
}

const joe = new Person("Joe");
const sal = new Person("Sal");

joe.printName();    //> "Joe"
sal.printName();    //> "Sal"
```
So that's pretty damn useful. We've just used `this` to attach a property and a method to an object and to return the property using the method.

However, methods in JavaScript are just functions, and functions are values which can be bound to new variables, given as arguments to other functions, and returned from functions. Which means we can do this:
```javascript
const printName = joe.printName;
printName;    //> ƒ () { console.log(this.name); }

printName();  //> (nothing prints)
```
Now that the function `printName` is being called from outside of the object context in which it found the value of `this.name`, it has no idea what `this.name` should resolve to. But it does actually know what `this` refers to:
```javascript
const name = "Mike";    // declared in Global Scope

printName();   //> "Mike"
```
It turns out that the global object (as well as modules) has its own `this` property. If the function you are executing doesn't have a `this` defined by its execution context, it will look default to the global `this`.
```javascript
console.log(this);    //> Window { ... }

console.log(window.globalThis);    //> Window { ... }
```
That still isn't that confusing. Let's go deeper.
```javascript
function anExample() {
    console.log(this);
    function aNestedExample() {
        console.log(this);
    }
    aNestedExample();
}
anExample();
//> Window { ... }
//> Window { ... }

const anObj = {};
anObj.aMethod = anExample;

anObj.aMethod();
//> { aMethod: f }
//> Window { ... }
```
And that right there is the heart of the matter. Even though we have attached the `anExample` function to an object as a method, the function inside of it is still referring to the global object.

![isn't that weird?](https://media.giphy.com/media/w6yT4hb1bODOcYS5i3/giphy.gif)

Why?

Turns out there are 2 important factors:

1) Is `"use strict"` mode enabled?
2) How is the function invoked?

#Is `"use strict"` enabled?

There's an additional factor! Let's slightly modify the example above to use `"use strict"`

```javascript
"use strict";

function anExample() {
    console.log(this);
    function aNestedExample() {
        console.log(this);
    }
    aNestedExample();
}
anExample();
//> undefined
//> undefined

const anObj = {};
anObj.aMethod = anExample;

anObj.aMethod();
//> { aMethod: f }
//> undefined
```

If `"use strict"` is enforced, JavaScript will not search outside of the function's execution context for a `this` value, so if the function does not define one for itself, `this` resolves to `undefined`.

#How is the function invoked?

If the function is invoked as a function without any object provided as a context for `this` to refer to, then `this` will refer to the `global` object. 
```javascript
function example() {
    console.log(this);
}
example();    //> Window { ... }

const anObj = {
    property: 5,
    method: function() {
        console.log(this);
        function noThis() {
            console.log(this);
        }
        hasThis();
    }
}
anObj.method();
//> { property: 5, method: f }
//> Window { ... }
```
`this` is *not* lexically scoped. Even if it is contained within a function which has a `this` value and is lexically located within an object, it still refers to the `global` object.

What actually matters is whether or not the function is invoked as a method:
```javascript
const anObj = {
    property: 5,
    method: function() {
        console.log(this);
        return function noThis() {
            console.log(this);
        }
    }
}
const anotherObj = {};

anObj.method()();
//> { property: 5, method: f }
//> Window { ... }

anotherObj.asAMethod = anObj.method();    
//> { property: 5, method: f }

anotherObj.asAMethod();
//> { asAMethod: f }
```
In this example, even though the function `noThis` is lexically within a method on another object which *does* have a `this` when invoked it doesn't have its own `this` *unless* it is invoked as a method on a new object. Otherwise refers to the `global` object.

So the actual notation that you use to invoke a method matters.
```javascript
anObject.method;    // Dot Notation: this == true
anObject["method"]; // Computed Access: this == true
asAFunction();      // Function invocation: this == false
```
The value of `this` is generated each time the function is invoked. Any function which isn't invoked as an object method will not generate a `this` value.

But there's one final twist. Object generator functions and classes *do* have a  `this` value when they are invoked, even though they aren't being called as a method:
```javascript
class Person {
    constructor(name) {
        console.log(this);
        this.name = name;
    }
}
const joe = new Person("Joe");
//> Person {}

function Person(name) {
    console.log(this);
    this.name = name;
}
const joe = new Person("Joe");
//> Person {}
```
And that makes sense, they're generating an object and need to be able to reference the object while it is being created in order to add properties and methods to it.

If we define a method on the `prototype`, it *still* refers to the created object correctly, because we're using a method call!
```javascript
Person.prototype.newMethod = function () {
    console.log(this);
}
joe.newMethod();    //> Person { name: "Joe" }
```

Ok, that's actually *kind* of sensible, but it sets a trap with nested functions where you aren't calling the nested function as a method.

There's two common solutions to that problem:

1) Save the value of `this` as a variable, e.g. `that`, `_this`, `self` or `_self`.
```javascript
const anObj = {
    property: 5,
    method: function() {
        const that = this
        function noThis() {
            console.log(this);
            console.log(that);
        }
        noThis();
    }
}
anObj.method();
//> Window { ... }
//> { property: 5, method: f }
```
Saving the value of `this` allows it to be used with normal lexical scoping rules.

2) Use Arrow Functions
```javascript
const anObj = {
    property: 5,
    method: function() {
        const that = this
        const noThis = () => {
            console.log(this);
            console.log(that);
        }
        noThis();
    }
}
anObj.method();
//> { property: 5, method: f }
//> { property: 5, method: f }
```
Arrow functions do not define their own `this` value, instead they look outwards up the lexical scope chain for a `this` value, acting just like you wish `this` would.

*However*, because they do not define their own `this` if you don't nest them inside of function defined with the `function` keyword and call *that* as a method from an object, your arrow function won't know what the value of `this` is either:
```javascript
const anObj = {
    method: () => console.log(this)
}
anObj.method();    //> Window { ... }
```

So if you want to use `this`:

1) Use dot `.` or bracket `[ ]` notation when calling your function.
2) Use `function` to define your methods instead of arrow functions.
3) Either bind the value of `this` or use arrow functions *within* your methods for lexical scope.
4) Don't use `this` *unless* you expect to use the function as a method or have prepared for it to refer to the `global` object instead.

#Ok, but why?

Whether or not JavaScript's solution to `this` is a good idea should be judged against the problem that it faces. Unlike languages like Ruby where objects own their methods and those methods are typically defined within or upon the object which `self` will refer to, JavaScript doesn't have formal methods.

Methods in JavaScript are actually key:value pairs on an object which stores the reference value to the function object. When calling a method with dot or bracket notation, the expression `object.method()` is actually two parts: `object.method` and the function invocation. `object.method` evaluates to `myMethodFunction` which is then is then invoked. 

Unlike Ruby, where the object receives a message and determines if it can respond to the message based upon the methods defined upon it, all JavaScript objects know is what keys they have defined and what values correspond to those keys. Since the functions used as methods can be defined anywhere and may be referenced by many different objects, there's no clear owner of any function and JavaScript is forced to determine `this` based upon the context by which it was called rather than how it was defined.

So this makes sense. It's complicated, it's tricky, and having `this` refer to `global` rather than lexical scope is a bad idea, but now that we understand that, we anticipate it and just use `that` or `=>` instead!