this is one of the most confusing parts of JavaScript for newcomers, mainly because it doesn't work the way it does in most other languages. In JavaScript, what this refers to isn't fixed by where a function is defined — it's determined by how the function is called.

Once you learn the handful of rules that decide this, the confusion mostly disappears.

Rule 1: Method Calls — this is the Object Before the Dot

const user = {
  name: "Maya",
  greet() {
    console.log(`Hi, I'm ${this.name}`);
  },
};

user.greet();

Output:

Hi, I'm Maya

Because greet() was called as user.greet(), this inside it refers to user.

Rule 2: Standalone Calls — this is undefined (or the global object)

const greetFn = user.greet;
greetFn(); // called standalone, no object before the dot

// In strict mode / modules, this is undefined here,
// so this.name throws: Cannot read properties of undefined

This is the classic trap: pulling a method off an object and calling it on its own loses the connection to that object entirely, because this is decided at call time, not definition time.

The Callback Gotcha — and How Arrow Functions Fix It

This exact problem shows up constantly with callbacks, like setTimeout:

const timer = {
  seconds: 3,
  start() {
    // Regular function: `this` here is NOT `timer` anymore
    setTimeout(function () {
      console.log(this.seconds); // undefined, or an error
    }, 100);

    // Arrow function: inherits `this` from start()'s scope
    setTimeout(() => {
      console.log(this.seconds); // 3, correctly
    }, 100);
  },
};

timer.start();

Output:

undefined
3

Regular functions get their own this based on how they're called — and a callback passed to setTimeout is called standalone, by the browser, not as a method on timer. Arrow functions don't have their own this at all; they simply use whatever this was in the surrounding code where they were written, which is exactly what you usually want inside a callback.

The Takeaway

Ask "how is this function being called?" rather than "where is it defined?" — that question answers what this will be in a regular function. If you're writing a callback and want it to keep the outer this, reach for an arrow function. This same mechanic is also what makes JavaScript's class methods work correctly when called as instance.method().