How this Is Bound
this is set by how a function is called, following four rules in priority order.
Syntax
new Fn() // this = new object
fn.call(obj) // this = obj
obj.fn() // this = obj
fn() // this = undefined (strict)The value of this is not decided where a function is written -- it is decided at the call site. Four rules, checked top to bottom:
- new binding --
new Fn()setsthisto the fresh object. - Explicit binding --
call,apply,bindset it by hand. - Implicit binding --
obj.method()setsthistoobj. - Default -- a plain
fn()getsundefinedin strict mode (the global object otherwise).
The classic trap: losing the receiver
Pull a method off its object -- pass it as a callback, assign it to a variable -- and the implicit binding is gone. const g = obj.method; g(); loses obj.
const btn = { label: 'OK', click() { return this.label; } };
const fn = btn.click;
fn(); // this is undefined -> crashArrow functions sidestep all four rules by having no this of their own (next lesson).
Example
Loading editor…
Press Run to execute the code.
When to use it
- Ensure a method on a class retains its this when extracted and passed as an event callback.
- Inspect this inside a regular function called in sloppy mode to understand why it is the global object.
- Use explicit binding to borrow a method from one object and run it in the context of another.
More examples
this in object method
When called as wallet.deposit(), this refers to wallet so the method can update the balance.
const wallet = {
balance: 100,
deposit(amount) {
this.balance += amount;
return this.balance;
}
};
console.log(wallet.deposit(50)); // 150this lost when method is detached
Extracting a method loses its binding; calling fn() sets this to undefined (strict) or the global object.
const obj = { name: "Widget", getName() { return this.name; } };
const fn = obj.getName; // detach
console.log(fn()); // undefined – this is global/undefined in strict modeBorrow a method with call
Uses call to invoke describe with different objects as this, borrowing the method without copying it.
function describe() {
return `${this.name} (${this.type})`;
}
const car = { name: "Sedan", type: "vehicle" };
const boat = { name: "Dinghy", type: "vessel" };
console.log(describe.call(car)); // "Sedan (vehicle)"
console.log(describe.call(boat)); // "Dinghy (vessel)"
Discussion