JavaScript call, apply, bind

Set `this` Explicitly

JavaScript call, apply, bind

Three function methods that let you choose what `this` is when a function runs. `call` and `apply` invoke immediately; `bind` makes a new function.

4 min read Level 3/5 #call#apply#bind
What you'll learn
  • Use `.call(thisArg, ...args)` to invoke with a chosen `this`
  • Use `.apply(thisArg, argsArray)` — same, but args as array
  • Use `.bind(thisArg)` to create a bound function

Every function comes with three built-in methods that let you control this. They’re tools for the situations where the default this rules don’t give you what you want.

call(thisArg, ...args)

Invokes the function with this set to thisArg. Arguments are passed individually.

call script.js
function greet(greeting) {
  console.log(`${greeting}, ${this.name}!`);
}

const ada = { name: "Ada" };

greet.call(ada, "Hello");   // "Hello, Ada!"
greet.call(ada, "Hi");      // "Hi, Ada!"
▶ Preview: console

apply(thisArg, argsArray)

Same as call, but the arguments come as an array.

apply script.js
function describe(greeting, mood) {
  console.log(`${greeting}, ${this.name}! Feeling ${mood}.`);
}

const ada = { name: "Ada" };

describe.apply(ada, ["Hi", "great"]);  // "Hi, Ada! Feeling great."
▶ Preview: console

bind(thisArg, ...args) — Make a Bound Function

bind doesn’t call the function — it returns a new function that, when called, has this permanently fixed.

bind returns a new function script.js
function greet() {
  console.log(`Hi, ${this.name}`);
}

const ada = { name: "Ada" };
const boundGreet = greet.bind(ada);

boundGreet();           // "Hi, Ada"
setTimeout(boundGreet, 0); // still "Hi, Ada" — bound stays bound
▶ Preview: console

bind is the classic fix for the “lost this” callback bug:

bind for callbacks script.js
const user = {
  name: "Ada",
  greet() {
    console.log(`Hi, ${this.name}`);
  },
};

// Without bind — this is lost when setTimeout calls the function:
// setTimeout(user.greet, 10);

// With bind:
setTimeout(user.greet.bind(user), 10);  // works
▶ Preview: console

In modern code, an arrow callback usually reads more clearly:

setTimeout(() => user.greet(), 10);

Both work — pick the one that’s clearer in context.

Partial Application With bind

bind also lets you pre-fill arguments — known as partial application.

Pre-fill arguments script.js
function multiply(a, b) {
  return a * b;
}

const double = multiply.bind(null, 2);  // a = 2 pre-filled
const triple = multiply.bind(null, 3);  // a = 3 pre-filled

console.log(double(10));  // 20
console.log(triple(10));  // 30
▶ Preview: console

The null is thisArg; we’re not using this here so it doesn’t matter.

Cheatsheet

MethodInvokes now?Args
fn.call(this, …)yesindividual
fn.apply(this, [])yesarray
fn.bind(this, …)no — returns new functionindividual (partial OK)

When You Actually Need These

In modern JavaScript, you’ll reach for call/apply/bind less often — arrow functions and class have absorbed many of their use cases. They still show up in:

  • Library code that needs to manage this carefully.
  • Borrowing methods from one type for another (Array.prototype.slice.call(arguments)).
  • Partial application without a wrapper function.

Up Next

Functions as values — passing them, returning them, building with them.

JavaScript Higher-Order Functions →