11 / 20 · Day 4
Day 4 · Concept 11

this binding

Four rules determine what this refers to: new-binding, explicit (call/apply/bind), implicit (the object before the dot), and default (global or undefined). Arrow functions opt out — they inherit this from where they were written.


1 · The four rules

js this.js
function showThis() { return this; }

// 1. Default — undefined in strict mode, globalThis otherwise
console.log(showThis() === globalThis);

// 2. Implicit — object before the dot
const obj = { showThis };
console.log(obj.showThis() === obj);

// 3. Explicit — call/apply/bind
console.log(showThis.call({tag: "x"}));

// 4. new
function Person(name) { this.name = name; }
const p = new Person("Alice");
console.log(p.name);

2 · The losing-this trap

js lose.js
const user = {
    name: "Alice",
    greet() { return `hi, ${this.name}`; },
};

console.log(user.greet());        // "hi, Alice"

// Detach the method — this is lost
const g = user.greet;
console.log(g());                 // "hi, undefined" — this is now undefined / global

// Fix with bind
const bound = user.greet.bind(user);
console.log(bound());             // "hi, Alice"

The most common this bug. Pass obj.method.bind(obj) or use arrow functions when handing methods to callbacks.

3 · Arrows don't bind this

js arrow-this.js
const counter = {
    count: 0,
    start() {
        // Without arrow: this inside setInterval callback is wrong
        // setInterval(function() { this.count++; }, 100);

        // With arrow: 'this' is the outer 'this' — the counter
        setInterval(() => {
            this.count += 1;
        }, 100);
    },
};
The rule. Use arrows for callbacks; named functions for object methods and constructors. Class methods can be arrow class-fields when you want auto-bind.

4 · call / apply / bind

js call-apply-bind.js
function intro(greet, punct) {
    return `${greet}, ${this.name}${punct}`;
}

const u = { name: "Alice" };

console.log(intro.call(u, "Hi", "!"));          // arguments listed
console.log(intro.apply(u, ["Hello", "."]));    // arguments as array
const bound = intro.bind(u, "Hey");
console.log(bound("?"));                         // 'this' + leading args fixed

5 · Common mistakes

  • Detaching a method. const fn = obj.method; fn() loses this.
  • Arrow methods on objects. { greet: () => this.name }this isn't the object.
  • Inner function inside a method. Inner has its own this. Use arrow or const that = this.
  • Forgetting new on a constructor. Person("x") without new sets properties on global (or throws in strict mode).

6 · When it clicks

  • You trace this to the call site by reflex.
  • You pick arrow vs function based on this needs.
  • .bind(this) in event handlers feels automatic.
Found this useful?