Forem

Cover image for "This" is Not What You Think: A Real-World Guide to the JavaScript this Keyword
NoobDev
NoobDev

Posted on

"This" is Not What You Think: A Real-World Guide to the JavaScript this Keyword

If you've ever found yourself debugging JavaScript and yelling, "Why is this undefined?!", you're not alone. The this keyword is one of the most misunderstood concepts in JavaScript. It's like that friend who acts differently depending on the situation—sometimes reliable, sometimes confusing, and occasionally just missing in action.

But don’t worry! In this blog, we’ll break down this in a fun way with real-world use cases, common pitfalls, and solutions to save you from the dreaded undefined is not a function errors.


Understanding this: The Golden Rule

The value of this depends on how a function is called, not where it's written.

Think of this like a restaurant waiter:

  • If you call them politely, they serve you well.
  • If you shout from across the street, they might ignore you.
  • If they’re not assigned to your table, they don’t know what to do.

In JavaScript, the context of this changes depending on where and how a function is called.


Use Case 1: this in Objects

Scenario: You’re building a simple user profile object that logs the username.

const user = {
  name: "Alice",
  greet: function () {
    console.log(`Hello, my name is ${this.name}`);
  }
};

user.greet(); // ✅ Hello, my name is Alice
Enter fullscreen mode Exit fullscreen mode

💡 What’s happening?

  • Here, this refers to user, because the function is called as user.greet().

Pitfall: If you store the method in a variable and call it separately…

const greetUser = user.greet;
greetUser(); // ❌ TypeError: Cannot read properties of undefined
Enter fullscreen mode Exit fullscreen mode

😱 Why?

  • Because this now refers to the global object (window in browsers, undefined in strict mode), not user.

🛠 Solution: Use .bind(this)

const greetUser = user.greet.bind(user);
greetUser(); // ✅ Hello, my name is Alice
Enter fullscreen mode Exit fullscreen mode

Use Case 2: this in Event Handlers

Scenario: You’re building a button that logs the text inside it when clicked.

const button = document.querySelector("#clickMe");

button.addEventListener("click", function () {
  console.log(`You clicked: ${this.innerText}`);
});
Enter fullscreen mode Exit fullscreen mode

💡 Why does this work here?

  • Because in regular functions, this inside an event listener refers to the element that triggered the event.

Pitfall: If you switch to an arrow function…

button.addEventListener("click", () => {
  console.log(`You clicked: ${this.innerText}`);
});
Enter fullscreen mode Exit fullscreen mode

😱 Uh-oh! this is now undefined.

  • Arrow functions don’t have their own this, they inherit from their surrounding scope (which in this case is the outer script, not the button).

🛠 Solution: Use a regular function or explicitly reference button inside an arrow function.

button.addEventListener("click", function () {
  console.log(`You clicked: ${this.innerText}`);
});

// OR

button.addEventListener("click", (event) => {
  console.log(`You clicked: ${event.target.innerText}`);
});
Enter fullscreen mode Exit fullscreen mode

Use Case 3: this in Classes

Scenario: You’re building a Car class and need to print the car’s details.

class Car {
  constructor(make, model) {
    this.make = make;
    this.model = model;
  }

  showCar() {
    console.log(`Car: ${this.make} ${this.model}`);
  }
}

const myCar = new Car("Tesla", "Model S");
myCar.showCar(); // ✅ Car: Tesla Model S
Enter fullscreen mode Exit fullscreen mode

💡 Why does this work here?

  • Because inside a class, this refers to the specific instance of the class.

Pitfall: If you pass showCar to setTimeout

setTimeout(myCar.showCar, 1000); 
// ❌ TypeError: Cannot read properties of undefined
Enter fullscreen mode Exit fullscreen mode

😱 Why?

  • setTimeout executes the function in a different context where this is not bound to myCar.

🛠 Solution: Bind this

setTimeout(myCar.showCar.bind(myCar), 1000);
Enter fullscreen mode Exit fullscreen mode

🛠 Or Use an Arrow Function

setTimeout(() => myCar.showCar(), 1000);
Enter fullscreen mode Exit fullscreen mode

Final Takeaways

When to use this in JavaScript?

✔ Inside objects → this refers to the object.

✔ Inside classes → this refers to the instance.

✔ In regular functions → this depends on how the function is called.

✔ Inside arrow functions → this is inherited from the surrounding scope.

Common Pitfalls (and Solutions)

Pitfall Solution
this is undefined in event listeners (arrow functions) Use a regular function or event.target
this changes when passing a method Use .bind(this)
this is lost inside setTimeout Use .bind(this) or an arrow function
this inside array methods doesn’t work as expected Use an arrow function

Conclusion

Understanding this is a rite of passage for JavaScript developers. Hopefully, this guide helps you avoid its many pitfalls and use it with confidence. The next time this confuses you, just ask: “Where was this function called?” 🎯

Top comments (0)