This is it! you got 'this'
Tags: javascript, beginners, interview
Published: 2019-06-20 17:35:19

---
title: This is it! you got 'this'
published: true
description: Explanation of 'this' keyword in javascript with examples
tags: javascript, beginners, interviews
cover_image: https://thepracticaldev.s3.amazonaws.com/i/ouhtyhe4zesthqonnw4j.jpg
canonical_url: https://shimphillip.netlify.com/blog/this-is-it-you-got-this
---
&nbsp;

`this` keyword must be one of the most confusing JavaScript concepts due to its dynamic nature of how it's invoked. If you find yourself reading this article, you probably have come across `this` several times and want to have a better understanding. I hope to make `this` crystal clear with practical examples and minimal jargon. Make sure you open up your console in your favorite browser and follow along!

---

&nbsp;

## `this` as global

The most straightforward way to identify `this` is when it's used as a global object. A global object is an object which can be accessed from anywhere in your JavaScript code. Browsers call this global object `window` and NodeJS call it `global`. This basic default binding is called **default binding**.

```javascript
console.log(this) // window
console.log(window) // window
console.log(this === window) // true
```

_Did you know `fetch` and `localStorage` are part of the global window object?_

Variables declared with `var` keyword and function declarations become properties of the window object. The properties of the global object can be accessed without dot or bracket notation. However, variables declared using `let` or `const` keywords don't become part of the global object, instead they will be stored inside an inaccessible environment.

```javascript
var age = 29
console.log(age) // 29
console.log(this.age) // 29
console.log(window.age) // 29

function sayHi() {
  console.log("Hi")
}
sayHi() // Hi
this.sayHi() // Hi
window.sayHi() // Hi

const sayHello = function() {
  console.log("Hello")
}
sayHello() // Hello
this.sayHello() // Uncaught TypeError: this.sayHello is not a function
window.sayHello() // Uncaught TypeError: window.sayHello is not a function
```


---

&nbsp;

## `this` in functions

`this` inside regular functions refer to the global object as well. Alternatively, we can also say that the __context__ of these functions is the global object. Context simply means the value of `this` at a given moment when your code is being run by the javascript engine (This is also known as the 'execution context').

```javascript
var whatIsThis = function() {
  console.log(this)
}

whatIsThis() // window
```

Word of caution: when __use strict__ mode is used, it won't allow the default binding of `this` to the `window` object. Therefore, the value of `this` results in undefined.

```javascript
"use strict"

var whatIsThis = function() {
  console.log(this)
}

whatIsThis() // undefined
```

&nbsp;

---

&nbsp;

## `this` in methods

Method means it's a function inside an object. <mark>`this` keyword inside methods is set to its parent object.</mark> This is called implicit binding because `this` is bound indirectly to the object it belongs to.

```javascript
var obj = {
  getThis: function() {
    return this
  },
}

// equivalent ES6 method
var obj = {
  getThis() {
    return this
  },
}

console.log(obj.getThis()) // obj
console.log(obj === obj.getThis()) // true
```

To access properties of the object inside your methods, you will need to explicitly use `this`. Otherwise, it will look for the variables with the same name inside the same function scope.

```javascript
var me = {
  name: "Phillip",
  getName() {
    const name = "Sunnie"
    console.log("My name is " + this.name)
    console.log("My name is " + name)
  },
}

me.getName() // My name is Phillip
// My name is Sunnie
```

&nbsp;

`me.getName()` gives expected strings. What if we assign the definition of our getName method to a variable outside the method? This will cause loss of implicit binding of `this` because the new getName function is no longer bound to the 'me' object. Instead, because our new getName is declared with `var` keyword, it's bound to the global window object and will try to search `this.name` as a property of the global object. Here is what official MDN doc says about this matter:

> In most cases, the value of this is determined by how a function is called. It can't be set by assignment during execution, and it may be different each time the function is called.

```javascript
var me = {
  name: "Phillip",
  getName: function() {
    console.log("My name is " + this.name)
  },
}

var getName = me.getName
me.getName() // My name is Phillip
getName() // My name is undefined
```

_Instead of seeing 'My name is undefined', you might get 'My name is '. That's because we previously used `this.name` globally so its key is there but its value got set to an empty string_

How about we extract the getName method out of the 'me' object and make it a standalone function. Then create another same-named getName property inside the 'me' object and assign the standalone getName function as a reference. Let's try calling them separately. If we call the standalone function by itself, as you observed previously, `this` will refer to the global object and tries to search the name from `window` object. If you call the function as a property of the 'me' object, the context of `this` will be the 'me' object. 

```javascript
function getName() {
  console.log("My name is " + this.name)
}

var me = {
  name: "Phillip",
  getName: getName,
}

getName() // My name is undefined
me.getName() // My name is Phillip
```

_Rule of thumb: Look at the left side of your method which it's called, `this` belongs to that object. If there isn't any, `this` belongs to the global object._

---

&nbsp;

## `this` using call, apply and bind.

We want to make our 'getName' function more reusable. Let's improve our code by using call, apply and bind functions. These are special functions that append to function definitions and directly invoke them. `call` and `apply` take objects as the first argument thus the methods will understand how to handle `this`. If no argument is passed, the context will be the global object.

```javascript
function getName() {
    console.log("My name is " + this.name)
}

var me = {
  name: "Phillip",
}

var you = {
  name: "Sunnie"
}

getName.call(me) // My name is Phillip
getName.apply(you) // My name is Sunnie
getName.call() // My name is undefined
```

The difference between `call` and `apply` is how you can pass in several arguments to the methods after the first argument. `call` will separate the values by commas and `apply` will also separate the values by commas but inside an array.

```javascript
function getInfo(age, hobby) {
    console.log(`My name is ${this.name}, I am ${age} and my hobby is ${hobby}`)
}

var me = {
  name: "Phillip",
}

var you = {
  name: "Sunnie"
}

getInfo.call(me, 29, "coding") // My name is Phillip, I am 29 and my hobby is coding
getInfo.apply(you, [28, "floral design"]) // My name is Sunnie, I am 28 and my hobby is floral design
```
_Helpful tip: <strong>C</strong>omma takes in <strong>c</strong>ommas and <strong>A</strong>pply takes in an <strong>a</strong>rray_

Often, we want to only associate certain methods with certain objects. `bind` helps us link a specific method to a specific object so that the value of `this` is predictable and can be found out by looking at its definition instead of investigating how it's invoked. Unlike call and apply, bind won't immediately invoke its attached function. This is called **explicit binding**

```javascript
function getName() {
  console.log("My name is " + this.name)
}

var me = {
  name: "Phillip",
}

getName = getName.bind(me)
getName() // My name is Phillip
```
_Don't forget to reassign it back to the method after you use bind!_

The practical use of bind is when a function is passed as a callback. Let's look at one example without the use of bind.

```javascript
var me = {
  name: "Phillip",
  getName: function() {
    console.log("My name is " + this.name)
  },
}

function calleMeMaybe(callback) {
  callback()
}

calleMeMaybe(me.getName) // My name is undefined
```

getName is undefined because, under the hood, this is what happens.

```javascript
callback = me.getName
```

Let's now bind getName to the 'me' object.

```javascript
var me = {
  name: "Phillip",
  getName: function() {
    console.log("My name is " + this.name)
  },
}
me.getName = me.getName.bind(me)

function calleMeMaybe(callback) {
  callback()
}

calleMeMaybe(me.getName) // My name Phillip
```
---
&nbsp;

## `this` in function constructors

In JavaScript, functions can serve as constructors to build new objects using the "new" keyword. `this` will be set to an instance (or an object) that is created by the function constructor.

```javascript
function Song(author) {
  this.author = author
  this.song = "Let it go"
  this.getInfo = function() {
    console.log(`${this.author} sang ${this.song}`)
  }
}

var song = new Song("Idina Menzel")
song.getInfo() // Idina Menzel sang Let it go

var song1 = new Song("Demi Lovato")
song1.getInfo() // Demi Lovato sang Let it go

// change of context
var getInfo = song1.getInfo 
getInfo() // undefined is sung by undefined
```
---
&nbsp;
## `this` with classes

Classes are modern function constructors. Inside classes, `this` will behave identically as the function constructors and will refer to particular objects that are created by the classes. Notice that "strict mode" is applied to classes by default.

```javascript
class Song {
  constructor(author) {
    this.author = author
    this.song = "Let it go"
  }

  getInfo() {
    console.log(`${this.song} is sung by ${this.author}`)
  }
}

const song = new Song("Idina Menzel")
song.getInfo() // Idina Menzel sang Let it go

const song1 = new Song("Demi Lovato")
song1.getInfo() // Demi Lovato sang Let it go

// change of context
const getInfo = song1.getInfo
getInfo() // Uncaught TypeError: Cannot read property 'song' of undefined
```

If you are familiar with React, you will notice we explicitly bind event handlers with the class itself. That is because event handler methods are passed as callbacks by some event listeners like onClick, onSubmit, etc... Remember, the callback functions lose their context.

```javascript
class Form extends React.Component {
  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this) // necessary
  }

  handleSubmit(event) {
    // Handle logic
  }

  render() {
    return <button onClick={this.handleSubmit}>Submit</button>
  }
}
```

---
&nbsp;
## `this` in arrow functions

JavaScript can get quirky and cause unexpected behaviors. What do you think the value of `this` will be in a function inside of a method? Our intuition tells us it will still refer to the parent object that the method belongs to. However, it doesn't. `this` actually will refer to the `window` object. Let's take our prior example and modify it.

```javascript
var me = {
  name: "Phillip",
  getName: function () {
    function innerFunction() {
      console.log("My name is " + this.name)
    }
    innerFunction();
  },
}

me.getName() // My name is undefined
```

There are multiple ways to fix this problem.

1. We can store `this` to a variable and reference the variable in the inner function. By convention, this variable is called 'self'. 
2. We can use `bind` inside the method to connect the inner function to the method's context.
3. Or use the arrow function.

> In arrow functions, `this` retains the value of the enclosing lexical context's `this`. - MDN

It means that the value of `this` is set to the function that contains the arrow function.

```javascript
// 1
var me = {
  name: "Phillip",
  getName: function () {
    var self = this;
    function innerFunction() {
      console.log("My name is " + self.name)
    }
    innerFunction();
  },
}

me.getName()

// 2
var me = {
  name: "Phillip",
  getName: function () {
    function innerFunction() {
      console.log("My name is " + this.name)
    }
    innerFunction = innerFunction.bind(this);
    innerFunction();
  },
}

me.getName()

//3
var me = {
  name: "Phillip",
  getName: function () {
    const innerFunction = () => {
      console.log("My name is " + this.name)
    }
    innerFunction();
  },
}

me.getName()
```
&nbsp;

---

## `this` with HTML

JavaScript event listeners get access to `this` when an event has been triggered. `this` then will refer to the HTML element that caused it. If the event listener callback function is declared as an arrow function, `this` will refer to the window object, its enclosing context.

```html
<h1 class="h1">Hello World</h1>
<h2 class="h2">Hi World</h2>
```

```javascript
const h1 = document.querySelector(".h1")
const h2 = document.querySelector(".h2")

h1.addEventListener("click", function(e) {
  console.log(e.target) // <h1 class="h1">Hello World</h1>
  console.log(this) // <h1 class="h1">Hello World</h1>
})

h2.addEventListener("click", e => {
  console.log(e.target) // <h2 class="h2">Hi World</h2>
  console.log(this) // window
})
```
&nbsp;

---
## Summary

Thank you for reading my article! 👏👏 I sincerely hope that it was helpful content to demystify any confusion you had with `this` keyword. I will leave with a summary of my lengthy article. Thanks again!

- `this` generally refers to the global object by default and in plain functions: default binding.
- in strict mode, `this` is undefined.
- Inside methods, `this` is the object which owns the method, but it depends on how `this` is invoked. Look at the left side of `this` to determine its value.
- Use call, apply to explicitly call the methods with desired objects. Use bind to glue together `this` to a specific object.
- In Arrow functions, look at the enclosing context to determine the value of `this`

&nbsp;