Q19 of 40 · JavaScript

How does the `this` keyword work across different JavaScript contexts?

JavaScriptMidjavascriptthisbindingarrow-functionsoop

Short answer

Short answer: `this` is determined at call time, not definition time (except arrow functions). In a method call `this` is the object; in a constructor it's the new instance; in a bare call (strict mode) it's `undefined`. Arrow functions inherit `this` from their enclosing lexical scope.

Detail

this is one of JavaScript's most confusing features because its value depends on how a function is called, not where it is defined.

Implicit binding (method call): obj.method()this is obj. Extracting the method loses the binding: const fn = obj.method; fn(); makes this undefined in strict mode.

Explicit binding: call(), apply(), and bind() set this explicitly.

new binding (constructor): new Fn() creates a new object, sets it as this, runs the constructor, and returns the object implicitly.

Default binding: A function called without a receiver has this === undefined in strict mode, or the global object in sloppy mode.

Arrow functions (lexical binding): Arrow functions capture this from their enclosing scope at definition time and never change. Ideal for event handlers and callbacks inside class methods.

In Page Objects: Using arrow class fields (increment = () => {}) ensures this is always the instance, even when the method is extracted and passed as a callback.

// EXAMPLE

const obj = {
  name: "qa",
  regular() { return this.name; },
  arrow: () => this?.name, // 'this' is outer scope (module = undefined)
};

console.log(obj.regular());       // "qa"
const fn = obj.regular;
// fn();                           // undefined or TypeError in strict mode

// Explicit binding
console.log(obj.regular.call({ name: "test" })); // "test"

// Class arrow field — safe for callbacks
class Counter {
  count = 0;
  increment = () => { this.count++; }; // always Counter instance
}
const c = new Counter();
const inc = c.increment; // extracting is safe
inc();
console.log(c.count); // 1

// WHAT INTERVIEWERS LOOK FOR

The four binding rules (implicit, explicit, new, default) plus arrow functions' lexical binding. Knowing that extracting a method loses `this`. Applied context — why this matters in callbacks, event listeners, and test helper classes.

// COMMON PITFALL

Using arrow functions as object methods when `this` should be the object — the arrow captures the outer (module/window) scope instead of the object.