All topics
Objectsintermediate

The this Keyword in Depth

How the value of this is determined dynamically at call time based on four binding rules, rather than lexically like a normal variable.

this is determined by how a function is called, not where it is defined. Four rules, checked in order.

this is like a name tag that gets handed to you fresh at the door of every single meeting you walk into (call site) — which meeting you're currently in determines what your tag says, rather than the tag being permanently stitched onto your shirt.

Key Concepts

1
1. new binding. this is the newly created object.
newthis
2
    function Dog(n) { this.name = n; }
    new Dog('Rex');        // this is the new object
3
2. Explicit binding. call, apply or bind set it.
callapplybind
4
    greet.call(user);      // this is user
5
3. Implicit binding. Called as a method, this is the object before the dot.
this
6
    obj.method();          // this is obj
7
4. Default. A plain call: undefined in strict mode, the global object in sloppy mode.
undefined
8
    method();              // this is undefined (strict)
9
Arrow functions ignore all four. They have no this; they use the enclosing scope's.
this
10
The bug this produces, constantly.
    const obj = {
      name: 'Asha',
      greet() { return this.name; }
    };
11
    obj.greet();                 // 'Asha'  -- implicit binding
12
    const fn = obj.greet;
    fn();                        // undefined -- the dot is gone
13
    setTimeout(obj.greet, 100);  // undefined -- same reason
14
Extracting a method loses the binding, because the binding came from the call site and there is no longer an object before the dot.
15
Three fixes.
    setTimeout(obj.greet.bind(obj), 100);
    setTimeout(() => obj.greet(), 100);
    // or define greet as a class field: greet = () => this.name;
16
The nested function trap, pre-arrow.
    const timer = {
      count: 0,
      start() {
        setInterval(function () {
          this.count++;       // this is NOT timer
        }, 1000);
      }
    };
17
The inner function is called plainly, so rule 4 applies. const self = this was the old fix; an arrow function is the current one.
const self = this
18
Where this is genuinely useful. Class methods, and objects with behaviour. In a plain function that does not need an object, this is a source of bugs rather than a feature — which is why arrow functions not having one is an improvement rather than a limitation.
this
19
What the interviewer is probing.1. "What determines this in a regular function?" Probing: the rules. Stalls: "Where it is defined." Moves up: the call site — a method call binds the object, a plain call gives undefined in strict mode, new binds the instance, and call/apply/bind set it explicitly.
20
2. "Why does passing a method as a callback lose this?" Probing: the detachment. Stalls: "It should keep it." Moves up: the function is called without its object, so this is not the instance; bind it or use an arrow.
21
3. "How do arrow functions change it?" Probing: lexical this. Stalls: "They bind it." *Moves up:* they have no this at all, so the lookup goes to the enclosing scope — which is why they fail as object methods.
22
4. "What is this in a DOM event handler?" Probing: the DOM rule. Stalls: "The window." Moves up: the element the handler is attached to for a regular function; an arrow keeps the enclosing this instead.