TypeOfNaN

How to use the right "this" value in JavaScript classes

Nick Scialli
March 18, 2023

If you’re using JavaScript classes, you’re likely used to using the this keyword to represent the object instantated form the class. But sometimes, this doesn’t work!

Creating a simple example

Let’s consider the following code:

class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log('Hello, my name is ' + this.name);
  }
}

const ben = new Person('Ben');
ben.greet();
// Hello, my name is Ben

In this example, this.name represents the name property on the instantiated object. When we call the greet method, we get the result we expect.

So what’s the problem? Well, let’s consider a small rewrite of this code:

class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log('Hello, my name is ' + this.name);
  }
}

const greet = new Person('Ben').greet;
greet();
// Uncaught TypeError: Cannot read properties of undefined (reading 'name')

Oh no, what happened? We didn’t appear to do anything different other than assigning the greet method into a new variable.

It’s all about call context

The this keyword in JavaScript is all about the context in which it is called. In our initial (working) example, greet was called on the ben object. ben is therefore the this ionside the greet method. However, when we assigned greet into a new variable, it’s not called on any object and therefore we get an error.

Ensuring the correct call context

We can make sure this always represents the instantiated object in greet by binding this to greet in the Person constructor:

class Person {
  constructor(name) {
    this.name = name;
    this.greet = this.greet.bind(this);
  }

  greet() {
    console.log('Hello, my name is ' + this.name);
  }
}

const greet = new Person('Ben').greet;
greet();
// Hello, my name is Ben

Now this works! We have told JavaScript that we want the current value of this to be bound to this.greet inside the Person constructor (this current value of this in the constructor will always be the instatiated object).

Conclusion

The this keyword is often misunderstood in JavaScript. Ultimately, it comes down to the context in which the function is called. If you potentially want this to be different based on its call context, then leaving it “unbound” is probably the way to go. However, in our example, we always want it to be tied to the class object. In this case, binding the this keyword is the right call.

Nick Scialli

Nick Scialli is a senior UI engineer at Microsoft.

© 2024 Nick Scialli