How is `this` determined in JavaScript?

JavaScript Functions & Scope Intermediate 2–3 Yrs3–5 Yrs Conceptual 1 min read

Quick Answer

this is set by how a function is called, not where it's defined. Rules in priority order: new → the new object; explicit call/apply/bind → the given object; method call obj.fn() → obj; otherwise → undefined in strict mode (or the global object). Arrow functions are the exception — they capture this from the enclosing scope.

this depends entirely on how the function is called. If it's called with new, this is the new instance. If you use call, apply or bind, it's whatever you passed. If you call it as a method — obj.method() — this is obj. And if it's just a plain function call, this is undefined in strict mode. Arrow functions break that pattern: they don't have their own this, they inherit it from where they were defined, which is exactly why they're handy for callbacks. The bug everyone hits is pulling a method off an object and passing it as a callback — this gets lost, and you fix it with bind or an arrow wrapper.

The common bug: passing a method as a callback loses its receiver.

const user = {
  name: 'Ada',
  greet() { return `Hi, ${this.name}`; }
};
const fn = user.greet;
fn();            // this is undefined -> error
setTimeout(user.greet, 0);   // same problem

Fixes: user.greet.bind(user), an arrow wrapper () => user.greet(), or define the method as an arrow-valued class field so it captures this. In event handlers, this is the element for a normal function but the enclosing scope for an arrow.