How to preserve the object context when calling the function later
When you detach a method (pass it as a callback), `this` is lost. Preserve it with: .bind(obj) to create a permanently-bound function, an arrow wrapper () => obj.method() that calls it as a method, or arrow class fields. bind is the canonical tool; arrow wrappers are common in callbacks/JSX.
The problem: this is determined by how a function is called, not where it's defined. Detach a method from its object and call it later, and this is lost:
const obj = {
name: "Ada",
greet() { return `Hi, ${this.name}`; },
};
const fn = obj.greet;
fn(); // ❌ this is undefined (strict) — "Hi, undefined"
setTimeout(obj.greet, 100); // ❌ same — called bare later
button.addEventListener("click", obj.greet); // ❌ this becomes the buttonThe fixes — ways to lock this to the object:
1. .bind() — the canonical tool
const bound = obj.greet.bind(obj);
bound(); // ✅ "Hi, Ada" — this permanently bound
setTimeout(obj.greet.bind(obj), 100); // ✅.bind(thisArg) returns a new function with this permanently set — it can't be re-bound. The standard, explicit solution.
2. Arrow function wrapper
setTimeout(() => obj.greet(), 100); // ✅
button.addEventListener("click", () => obj.greet()); // ✅You're not binding — you're calling obj.greet() as a method (with obj. at the call site) inside the arrow. The arrow itself just defers the call. Very common in callbacks and JSX event handlers.
3. Arrow function as a class field
class Greeter {
name = "Ada";
greet = () => `Hi, ${this.name}`; // arrow field captures the instance's this
}
const g = new Greeter();
const fn = g.greet;
fn(); // ✅ "Hi, Ada"The arrow class field captures this lexically at construction, so it survives detachment. Common in React class components (avoids binding handlers in the constructor).
4. call / apply — for immediate calls
fn.call(obj) / fn.apply(obj) invoke immediately with a given this — but they don't help for "call later," which is the question. bind is the "later" version.
When you hit this
Passing methods as callbacks — setTimeout, addEventListener, .map(), array methods, React event handlers, promise .then(). The fix is bind or an arrow wrapper.
The framing
"this is set by how a function is called, so detaching a method and calling it later loses it. To preserve it: .bind(obj) returns a new function with this permanently locked — the canonical, explicit fix. An arrow wrapper () => obj.method() works differently — it defers a method call, keeping obj. at the call site. And an arrow class field captures the instance's this lexically so it survives detachment — common in React class components. call/apply set this but only for an immediate call, not for 'later.'"
Follow-up questions
- •What's the difference between bind and an arrow wrapper?
- •Why does an arrow class field preserve `this`?
- •Can you re-bind a function that's already bound?
- •Why don't call/apply solve the 'call later' case?
Common mistakes
- •Passing obj.method directly as a callback and losing this.
- •Thinking call/apply help for deferred calls (they're immediate).
- •Trying to re-bind an already-bound function.
- •Using a regular function where an arrow's lexical this was needed.
Performance considerations
- •bind and arrow wrappers create a new function each time — in React, creating them inline in render can defeat memoization of child components; stabilize with useCallback or class fields when it matters.
Edge cases
- •Double-binding — the first bind wins.
- •bind also pre-fills arguments (partial application).
- •Arrow functions ignore bind/call/apply for `this`.
- •Event handler needing both `this` and the event object.
Real-world examples
- •Binding event handlers in React class components (or using arrow class fields).
- •Passing a method to setTimeout/addEventListener with .bind or an arrow wrapper.