Back to JavaScript
JavaScript
medium
mid

How do you preserve an object's context when calling a function later in JavaScript?

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.

4 min read·~8 min to think through

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:

js
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 button

The fixes — ways to lock this to the object:

1. .bind() — the canonical tool

js
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

js
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

js
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.

Senior engineer discussion

Seniors explain `this` is call-site-determined, give bind as the canonical fix, distinguish it from the defer-a-method-call arrow wrapper, cover arrow class fields, and note call/apply are for immediate invocation — plus the new-function-per-render perf caveat.

Related questions