Explorer
JavaScript

call apply bind in js

JavaScript Theory & Concepts

Call, Apply, and Bind in JavaScript

Explicit context control, function borrowing, and partial application mechanics.

📖 The Story & Real-World Analogy

The Race Car Driver and the Rental Agency

"Imagine you are a professional race car driver (a function), but you do not own a vehicle (`this`). You walk into a luxury rental agency: • **call()**: You rent a Ferrari right now. You list your helmet and gloves individually one-by-one (`drive.call(ferrari, "helmet", "gloves")`) and hit the gas immediately. • **apply()**: Same immediate drive, but you hand over all your gear packed inside a single travel bag / array (`drive.apply(ferrari, ["helmet", "gloves"])`). • **bind()**: You do not drive today. You sign a reserved contract with the agency, locking the Ferrari to you forever. Next month, whenever you turn the key, that Ferrari is already yours."

`call`, `apply`, and `bind` allow functions to borrow methods or explicitly set execution context (`this`). While `call` and `apply` execute immediately, `bind` returns a new bound function for deferred execution.

⚙️ How It Works Under The Hood (Step-by-Step)
1

Function.prototype.call(thisArg, ...args)

Invokes the target function immediately. Sets `this` to `thisArg` and passes arguments individually as a comma-separated list.

2

Function.prototype.apply(thisArg, [argsArray])

Invokes the target function immediately. Sets `this` to `thisArg` and accepts arguments as a single array or array-like object.

3

Function.prototype.bind(thisArg, ...args)

Does not execute immediately. Returns a new function with `this` permanently bound to `thisArg`, pre-filling any initial arguments (Currying / Partial Application).

4

Method Borrowing Pattern

Allows an object lacking a method to borrow it from another prototype (e.g., borrowing `Array.prototype.slice` or `Object.prototype.toString`).

💻 Interactive Code Walkthrough

Comparing call, apply, bind, and writing a clean myBind polyfill:

JAVASCRIPT
const chef = { name: "Gordon Ramsay" };

function prepareDish(spice, dessert) {
  return `${this.name} cooked with ${spice} and served ${dessert}`;
}

// 1. call (comma-separated args, runs immediately)
console.log(prepareDish.call(chef, "Paprika", "Soufflé"));

// 2. apply (array of args, runs immediately)
console.log(prepareDish.apply(chef, ["Oregano", "Tiramisu"]));

// 3. bind (returns a new function for later execution)
const gordonSpecial = prepareDish.bind(chef, "Truffle Oil");
console.log(gordonSpecial("Lava Cake"));

// 4. Custom Polyfill for bind
Function.prototype.myBind = function(context, ...boundArgs) {
  const originalFn = this;
  if (typeof originalFn !== "function") throw new TypeError("Not callable");

  return function(...callArgs) {
    return originalFn.apply(context, [...boundArgs, ...callArgs]);
  };
};
Console Output:
CODE
Gordon Ramsay cooked with Paprika and served Soufflé
Gordon Ramsay cooked with Oregano and served Tiramisu
Gordon Ramsay cooked with Truffle Oil and served Lava Cake
⚠️ Common Pitfalls & Interview Traps
Trap
Attempting to Re-bind a Bound Function

The Risk: `const fnB = fnA.bind(obj1); const fnC = fnB.bind(obj2);` - Calling `fnC()` still binds `this` to `obj1`!

The Fix: A bound function cannot have its `this` modified by subsequent `bind`, `call`, or `apply` calls. The first binding is permanent.

⚡ 30-Second Quick Revision Cheat Sheet (TL;DR)
  • ✓ Mnemonic: **A**pply takes an **A**rray; **C**all takes **C**ommas.
  • ✓ Both `call` and `apply` execute immediately.
  • ✓ `bind` returns a new function with locked `this` and optional preset arguments.
  • ✓ Bound functions cannot be overridden by subsequent `bind` or `call` invocations.
  • ✓ Method borrowing allows objects to share methods without inheritance.

Finished this lesson?

Mark this chapter complete to update your learning streak and unlock the next lesson.