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 is a senior UI engineer at Microsoft.