Why does a method lose its this when you pass it as a callback, and how do you fix it?
this is decided by how a function is called, not where it is defined. A detached method is called plainly, with no object before the dot, so this is lost. Fix it with bind, an arrow wrapper or an arrow class field.
Explain it simply
user.hello() has an object before the dot, so JavaScript sets this to user. If you copy the method into a variable and call f(), there is no object before the dot any more, so this is gone. It is like a delivery boy who knows your flat only because the order came with your name on it; strip the label and he is lost.
This happens all the time with setTimeout(user.hello, 100) and button.addEventListener("click", user.hello).
Three fixes: user.hello.bind(user), a wrapper () => user.hello(), or in a class an arrow function field.
Example
class User {
constructor() { this.name = "Ravi"; }
hello() { return "Hi " + this.name; }
}
const u = new User();
console.log(u.hello()); // Output: Hi Ravi
const detached = u.hello;
try {
detached();
} catch (e) {
console.log(e.name); // Output: TypeError
}
console.log(detached.bind(u)()); // Output: Hi Ravi
const wrapped = () => u.hello();
console.log(wrapped()); // Output: Hi RaviClass bodies are strict, so a lost this is undefined and reading .name throws.
What to say in the interview
"this depends on the call site. Passing user.hello as a callback detaches it from user, so it runs as a plain call. I fix it with bind, with an arrow wrapper, or by defining the method as an arrow class field."
Common mistakes
- Assuming this is fixed at the place the method is written.