Few things in JavaScript confuse developers as much as the keyword this. Depending on how and where you use it, this can point to completely different things.

In this post, we’ll break down what this really means, how it behaves in different situations, and how to avoid common mistakes.


🧠 What is this?

In JavaScript, this is a special keyword that refers to the context in which a function is called.

In other words:

this is not about where the function is written. It’s about how the function is called.


🧭 In the global scope

In the browser:

console.log(this); // window

In the global scope, this refers to the global object (window in browsers, global in Node.js).


🧱 Inside an object method

When a function is called as a method of an object, this refers to that object.

const user = {
  name: 'Marta',
  greet() {
    console.log('Hi, I am ' + this.name);
  }
};

user.greet(); // "Hi, I am Marta"

Here, this points to user because greet is being called through user.


🧩 Detached function

If you assign the method to a variable and call it, you lose the context:

const greet = user.greet;
greet(); // "Hi, I am undefined"

Now this is not pointing to user anymore. It’s pointing to the global object (or undefined in strict mode).


🧰 Using bind, call, and apply

You can manually set the value of this with bind, call, or apply.

const greetMaria = user.greet.bind(user);
greetMaria(); // "Hi, I am Maria"

  • bind returns a new function with this set to the object
  • call and apply invoke the function immediately with a specific this

📦 Arrow functions and this

Arrow functions behave differently. They don’t have their own this. Instead, they inherit this from the surrounding scope.

const user = {
  name: 'Maria',
  greet: () => {
    console.log('Hi, I am ' + this.name);
  }
};

user.greet(); // "Hi, I am undefined"

Arrow functions are great for preserving this in places like callbacks.

Example in a class:

class Timer {
  seconds = 0;

  start() {
    setInterval(() => {
      this.seconds++;
      console.log(this.seconds);
    }, 1000);
  }
}

Here, this.seconds++ works because the arrow function keeps the this from the start method.


✅ Recap

  • In the global scope, this refers to the global object
  • In a method, this refers to the object the method was called on
  • Arrow functions inherit this from their surrounding scope
  • You can control this using bind, call, and apply

📌 Conclusions

Understanding this is all about knowing how your function is being called.

If you're inside an object method, this likely refers to that object. If you're using arrow functions, this is inherited. And if you're seeing unexpected behavior, try using bind to lock down the context.