call apply bind in js
Call, Apply, and Bind in JavaScript
Explicit context control, function borrowing, and partial application mechanics.
The Race Car Driver and the Rental Agency
`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.
Function.prototype.call(thisArg, ...args)
Invokes the target function immediately. Sets `this` to `thisArg` and passes arguments individually as a comma-separated list.
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.
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).
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`).
Comparing call, apply, bind, and writing a clean myBind polyfill:
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]);
};
};
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
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.
- ✓ 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.