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
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
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
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
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 fixed5 · Common mistakes
- Detaching a method.
const fn = obj.method; fn()losesthis. - Arrow methods on objects.
{ greet: () => this.name }—thisisn't the object. - Inner
functioninside a method. Inner has its ownthis. Use arrow orconst that = this. - Forgetting
newon a constructor.Person("x")withoutnewsets properties on global (or throws in strict mode).
6 · When it clicks
- You trace
thisto the call site by reflex. - You pick arrow vs function based on
thisneeds. .bind(this)in event handlers feels automatic.
Found this useful?