This in JavaScript

Hey ,

I'm thrilled to help you learn JavaScript. Unfortunately, you've landed on a page where you cannot access with your current purchase.

Please upgrade (use this link) access this content.

I'm super eager to help you learn more!

This in JavaScript

Let’s take a pause and learn about this.

this is an important keyword in Object Oriented Programming. Unfortunately, the value of this changes depending on its surrounding context, which confuses the heck out of people.

I want to show you the different values this will be in different contexts, so you don’t get confused.

Six different contexts

The value of this changes depending on its context. There are six different contexts:

  1. this when used globally
  2. this in a simple function
  3. this in a constructor
  4. this in an instance
  5. this in a method
  6. this in an arrow function

When this is used globally

this is Window if you used it globally.

console.log(this)
This is window.

When this is used in a simple function

this is always Window if you use it in a simple function.

When I say simple function, I mean:

  1. Functions that are declared with the function keyword
  2. Functions that are NOT methods of an object
function sayThis () {
  console.log(this)
}
This is window.

When this is used in a constructor

When this is used in a constructor, it refers to the instance that will be created.

function Human (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
  console.log(this)
}

Constructors look like simple functions, which can be a source of confusion.

When you create instances from constructors, you must use the new keyword. If you use the new keyword, this will refer to the instance.

// DO THIS
const zell = new Human('Zell', 'Liew')
This in a constructor.

If you don’t use the new keyword, you will call the constructor like a simple function. When you call the constructor like a simple function, this refers to Window. Properties you declared with this will be added as global variables.

// DON'T DO THIS
const zell = Human('Zell', 'Liew')
This is window.
Firstname became a property of Window.

The same thing applies to this in a class’s constructor function.

class Human {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
    console.log(this)
  }
}
This in a constructor.

When this is used in an instance

When this is used in an instance, it refers to the instance.

function Human (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
  console.log(this)
}

const zell = new Human('Zell', 'Liew')
This points to the instance.

When this is used in a method

When this is used in a method, this refers to the object that calls the method.

const object = {
  sayThis () {
    console.log(this)
  }
}

object.sayThis()
This points to the object that called the method.

When this is used in an arrow function

When this is used in an arrow function, this will be the this value in the surrounding lexical scope.

Arrow functions change MANY things, so there are two best practices you need to know.

Best Practice #1: Don’t use arrow functions to create methods

When you use Object Oriented Programming, you may need to call a method from another method. If you want to do this, you need this to point back to the instance (which called the method).

Example:

Let’s build a Human with a sayHi method. sayHi says Hi!, then proceeds to end the conversation by saying the person’s name.

We can use a getFullName method that returns the full name of the person inside sayHi.

function Human (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}

Human.prototype.getFullName = function () {
  return this.firstName + ' ' + this.lastName
}

Human.prototype.sayHi = function () {
  console.log(`Hi! My name is ${this.getFullName()}`)
}

An instance can use the sayHi method and you’d expect it to work. It works because this points back to the instance.

const zell = new Human('Zell', 'Liew')
zell.sayHi()
Zell says hi.

Watch what happens if you change sayHi to an arrow function.

Human.prototype.sayHi = _ => {
  console.log(`Hi! My name is ${this.getFullName()}`)
}

// ...
zell.sayHi()
Error, this.getFullname is not a function.

Why?

In this case, this inside sayHi points to Window. Since Window doesn’t have a getFullName method, calling getFullName will result in an error.

this points to Window because Window is the lexical this value. We can verify that this is Window by logging it.

Human.prototype.sayHi = _ => {
  console.log(this)
  console.log(`Hi! My name is ${this.getFullName()}`)
}

// ...
zell.sayHi()
This is windows.

In short: Do not use arrow functions to create methods!

Best Practice #2: Use arrow functions to create functions INSIDE methods

this always points to Window when it is used in a simple function. The statement is true even if you create a simple function inside a method.

const object = {
  this () {
    function sayThis () {
      console.log(this)
    }
    sayThis()
  }
}

object.this()
This is Window.

We usually want this to be the object when we use this inside a method. (So we can call other methods).

One way is to assign this to another variable. We often call this variable self or that. We’ll then use self or that inside the function.

const object = {
  this () {
    const self = this
    function sayThis () {
      console.log(self)
    }
    sayThis()
  }
}

object.this()
This is the object.

Another way is to create a new function with bind.

const object = {
  this () {
    function sayThis () {
      console.log(this)
    }
    const correctSayThis = sayThis.bind(this)
    correctSayThis()
  }
}

object.this()
This is the object.

If you use arrow functions, you don’t need to use self, that, or bind. You can write the arrow function directly, and this will point to the object (because the surrounding this value is the object).

const object = {
  hello () {
    const sayThis = _ => {
      console.log(this)
    }
    sayThis()
  }
}

object.hello()
This is the object.