call, apply, and bind

⭐ Interview Importance: HIGH
⏱️ Revision Time: 3 min

TL;DR

Every traditional function in JavaScript has three built-in methods: call(), apply(), and bind(). They allow you to explicitly force a function to use a specific object as its this context.

  • call: Executes immediately, takes arguments separated by commas.
  • apply: Executes immediately, takes arguments as an array.
  • bind: Does NOT execute immediately. Returns a new function with this permanently locked in.

Mental Model

How It Works

Historically, these methods were used heavily for “method borrowing” (e.g., forcing an Array-like object to use the Array.prototype.slice method). In modern JavaScript, bind is still heavily used in React (class components) and event listeners to ensure callbacks don’t lose their context.

Example

const wizard = { name: "Merlin" };
const warrior = { name: "Arthur" };

// A generic function not attached to any object
function attack(weapon, damage) {
  console.log(`${this.name} attacks with ${weapon} for ${damage} damage!`);
}

// 1. call() - Pass arguments normally
attack.call(wizard, "Fireball", 50); 
// "Merlin attacks with Fireball for 50 damage!"

// 2. apply() - Pass arguments as an array (useful for dynamic args)
attack.apply(warrior, ["Excalibur", 100]); 
// "Arthur attacks with Excalibur for 100 damage!"

// 3. bind() - Creates a new locked function for later use
const wizardAttack = attack.bind(wizard, "Staff"); 
// We locked 'this' to wizard, and locked the first arg to "Staff"

wizardAttack(20); // "Merlin attacks with Staff for 20 damage!"

Common Output Question

const person = { name: "Bob" };

function sayHi() {
  console.log(this.name);
}

const bound1 = sayHi.bind(person);
const bound2 = bound1.bind({ name: "Alice" });

bound2();

Q: What does this output and why?
A: "Bob".
You can only bind() a function once. When sayHi.bind(person) creates a new function, the this context is permanently locked to person. Any subsequent attempts to bind() that new function will be completely ignored by the JavaScript engine.

Senior Interview Question

Q: In modern ES6+ JavaScript, apply() is rarely used. What feature replaced its primary use case?

A: The Spread Operator (...).
Historically, if you had an array of numbers [1, 5, 3] and wanted to pass them to Math.max(), you couldn’t pass the array directly. You had to use Math.max.apply(null, [1, 5, 3]) to spread the array into arguments.
Today, you simply write Math.max(...[1, 5, 3]), rendering apply() mostly obsolete outside of legacy codebases.