bind, call, and apply

All three control what this means inside a regular function. The difference is when the function runs and how you pass its arguments.

One idea, three methods

call

Runs the function now. Pass arguments one by one.

apply

Runs the function now. Pass arguments in an array or array-like object.

bind

Returns a new function for later. It can also prefill arguments.

MethodShapeRuns now?Result
callfn.call(thisArg, a, b)YesFunction's return value
applyfn.apply(thisArg, [a, b])YesFunction's return value
bindfn.bind(thisArg, a, b)NoA new function

First, understand this

For a regular function, this usually depends on how the function is called. Pulling a method away from its object also pulls away the call-site context.

const account = {
  owner: "Mira",
  introduce() {
    return `I am ${this.owner}`;
  }
};

account.introduce();       // "I am Mira"

const introduce = account.introduce;
introduce();               // `this` is no longer `account`

The question to ask: what value sits to the left of the dot at the call site? Explicit methods such as call, apply, and bind let you supply that value yourself.

call invokes with separate arguments

The first argument becomes this. Every later argument goes to the function in order.

function describe(role, punctuation) {
  return `${this.name} is a ${role}${punctuation}`;
}

const person = { name: "Asha" };

describe.call(person, "designer", "!");
// "Asha is a designer!"

apply invokes with collected arguments

apply is handy when the arguments already live in an array. Modern spread syntax often reads more naturally when no custom this value is needed.

With apply

const scores = [18, 31, 24];

Math.max.apply(null, scores);
// 31

With spread syntax

const scores = [18, 31, 24];

Math.max(...scores);
// 31

bind makes a reusable function

bind does not call the original function. It creates a new function whose this value is fixed.

Keep the method's context when passing it elsewhere.
const user = {
  name: "Dev",
  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

const greetDev = user.greet.bind(user);

setTimeout(greetDev, 100);
// "Hello, Dev"
bind can prefill arguments. This is partial application.
function multiply(a, b) {
  return a * b;
}

const double = multiply.bind(null, 2);

double(7); // 14

Borrow a method

A function does not belong permanently to the object where it was defined. call can run it with another compatible object as this.

const member = {
  firstName: "Nikhil",
  fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
};

const guest = { firstName: "Rhea", lastName: "Sen" };

member.fullName.call(guest);
// "Rhea Sen"

Arrow functions are different

Arrow functions do not create their own this. They capture it from the surrounding scope, so call, apply, and bind cannot replace it.

const showName = () => this.name;

showName.call({ name: "Asha" });
// not "Asha"

Common mistakes

  • Calling the result of call later.

    call has already run the function. Use bind when an event handler or timer needs a function.

  • Passing an array to call.

    fn.call(obj, [1, 2]) passes one array argument. Use apply or spread when the function expects two arguments.

  • Trying to rebind an arrow function.

    Use a regular function when the caller should control this.

Check your understanding

  1. Which method returns a function without running it?
    Show answer

    bind. It creates a new function with fixed context and optional prefilled arguments.

  2. What is the difference between fn.call(obj, 1, 2) and fn.apply(obj, [1, 2])?
    Show answer

    Both run immediately with obj as this. call takes separate arguments, while apply takes one array-like collection.

  3. Can bind change the this value captured by an arrow function?
    Show answer

    No. An arrow function gets this from the scope where the arrow was created.