All topics
Functionsintermediate

Function.prototype.call, apply, and bind

Three methods for explicitly controlling what this refers to inside a function, with different argument-passing conventions.

Three ways to control what this refers to inside a function.

call/apply are like temporarily lending someone your ID for one specific transaction; bind is like getting them a permanent duplicate ID card that always identifies them as you, no matter which counter they use it at later.

Key Concepts

1
    function greet(greeting, punct) {
      return `${greeting}, ${this.name}${punct}`;
    }
${greeting}, ${this.name}${punct}
2
    const user = { name: 'Asha' };
3
    greet.call(user, 'Hello', '!');     // arguments listed
    greet.apply(user, ['Hello', '!']);  // arguments in an array
    const bound = greet.bind(user);     // returns a new function
    bound('Hello', '!');
4
call and apply invoke immediately and differ only in how arguments are passed. The mnemonic: apply takes an array.
callapply
5
bind does not invoke. It returns a new function with this permanently fixed — and it cannot be changed again:
bindthis
6
    const b = greet.bind(user);
    b.call(other, 'Hi', '!');   // still uses user
7
bind also does partial application.
    const hello = greet.bind(user, 'Hello');
    hello('!');                  // 'Hello, Asha!'
bind
8
Where these actually get used.Preserving this in a callback, before arrow functions:
this
9
    setTimeout(this.handleClick.bind(this), 100);
    setTimeout(() => this.handleClick(), 100);   // modern equivalent
10
Borrowing a method from another type:
11
    Array.prototype.slice.call(arguments);       // array-like -> array
    Array.from(arguments);                       // modern
12
    Object.prototype.toString.call(value);       // reliable type check
13
That last one is still the correct way to distinguish an array from a date from null, so it has not been replaced.
null
14
Extracting a method safely.
15
    const fn = obj.method;      // this is lost
    fn();                       // undefined or the global object
16
    const fn = obj.method.bind(obj);   // safe
17
This is why React class components bound their handlers in the constructor, and it is what the bug looks like when they did not.
18
What arrows changed. They cover the callback case, which was most of the use. call and apply remain for borrowing methods and for dynamic invocation; bind remains for extracting a method that must keep its object.
callapplybind
19
One note on new. A bound function used with new ignores the bound this — the constructor's behaviour wins, which is deliberate and rarely encountered.
newthis
20
What the interviewer is probing.1. "What is the difference between the three?" Probing: the signatures. Stalls: "They all set this." Moves up: call takes arguments individually, apply takes an array, and bind returns a new function rather than invoking.
21
2. "Can you rebind a bound function?" Probing: the permanence. Stalls: "Yes." Moves up: no — the first bind wins and later calls or binds cannot change this.
22
3. "Why is apply useful with Math.max?" Probing: spreading an array. Stalls: "It is not." Moves up: Math.max takes individual arguments, so apply spreads an array into it — though spread syntax now does this more clearly.
23
4. "Does bind affect an arrow function?" Probing: the interaction. Stalls: "Yes." *Moves up:* no — an arrow has no own this, so bind cannot change it.