Sentry Answers>JavaScript>

Wrong References to `this`

Wrong References to `this`

Valerie M.

The Problem

The this keyword is used in JavaScript to refer to an object. The object it refers to depends on how this is being invoked. The following table shows the different global and function contexts that this can be used:

Where this is calledWhat it refers to
Object methodThe object
Used aloneThe global object
In a functionThe global object
In a function (strict)undefined
In an eventThe element receiving event

In light of the above uses of this, there are bound to be problems where the this keyword ends up referring to the wrong object. We’re going to explore how these incorrect references come about and how to fix them.

The Solution

To understand how wrong references to this can occur, let’s look at the following code example where this is used when working with functions:

Click to Copy
function myFunction() { return this; } // returns "[object Window]"

In the above example, this refers to the global object, which is an open browser window.

In strict mode, as shown below, this becomes undefined because default binding is not allowed. In this case, this should be used in objects you created.

Click to Copy
'use strict'; function myFunction() { return this; } // returns "undefined"

The use of this is further explained below in the case of using it inside an object method.

Click to Copy
const person = { firstName: 'John', lastName: 'Doe', id: 1, fullName() { return `${this.firstName} ${this.lastName}`; }, }; // Outputs "John Doe" console.log(person.fullName());

If you want to output a person’s full name, this is used and will refer to the person object.

However, things can become confusing when you want to use nested functions inside an object:

Click to Copy
const person = { firstName: 'John', lastName: 'Doe', id: 1, fullName() { function name() { this.firstName = 'Jane'; return this; } const p = name(); return `${this.firstName} ${p.firstName}`; }, }; // Outputs "John Jane" console.log(person.fullName());

The above code outputs the result as expected because of object method binding, where each reference to this is bound to the firstName of the calling object where:

  • this.firstName returns “John”, and
  • p.firstName returns “Jane”.

However, if we were to modify the return statement for fullName to have the following (instead of outputting the firstName):

Click to Copy
const person = { firstName: 'John', lastName: 'Doe', id: 1, fullName() { function name() { return this; } const p = name(); return `${this} ${p}`; }, }; // Outputs [object Object] [object Window] console.log(person.fullName());

You’ll notice that the this returned inside the name() function refers to the object Window, which is a global object. Even though this is used inside an object, it is still seen as being used alone and inside a function. As such, it refers to the global object.

If we want to bind this to any object properties defined inside name(), one way is to assign the this value from the calling object to another variable that would be used inside the nested function.

Click to Copy
const person = { firstName: 'John', lastName: 'Doe', id: 1, fullName() { const that = this; function name() { return that; } return name(); }, };

Furthermore, methods such as bind(), call(), and apply() can be used to refer this to any object.

The code below illustrates the use of the bind() method where the member object borrows a property from the person object. In this case, the this keyword refers to the member object, so we get the output “Steve Doe”.

Click to Copy
const person = { firstName: 'John', lastName: 'Doe', id: 1, fullName() { return `${this.firstName} ${this.lastName}`; }, }; const member = { firstName: 'Steve', lastName: 'Doe', }; const p = person.fullName.bind(member); // Outputs "Steve Doe" console.log(p());
  • ResourcesImprove Web Browser Performance - Find the JavaScript code causing slowdowns
  • SentryJavascript Error Monitoring & Tracing
  • ResourcesJavaScript Frontend Error Monitoring 101
  • Syntax.fmListen to the Syntax Podcast
  • Syntax.fm logo
    Listen to the Syntax Podcast

    Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.

    SEE EPISODES

Considered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.