Using function.call to Call a Function

Examples

Using call() to invoke a function and specifying the this value

In the example below, when we call greet, the value of this will be bound to object obj, even when greet is not a method of obj.

function greet() {
  console.log(this.animal, "typically sleep between", this.sleepDuration);
}

const obj = {
  animal: "cats",
  sleepDuration: "12 and 16 hours",
};

greet.call(obj); // cats typically sleep between 12 and 16 hours


Using call() to invoke a function without specifying the first argument

If the first thisArg parameter is omitted, it defaults to undefined. In non-strict mode, the this value is then substituted with globalThis (which is akin to the global object).

globalThis.globProp = "Wisen";

function display() {
  console.log(`globProp value is ${this.globProp}`);
}

display.call(); // Logs "globProp value is Wisen"

In strict mode, the value of this is not substituted, so it stays as undefined.

"use strict";

globalThis.globProp = "Wisen";

function display() {
  console.log(`globProp value is ${this.globProp}`);
}

display.call(); // throws TypeError: Cannot read the property of 'globProp' of undefined


Transforming methods to utility functions

call() is almost equivalent to a normal function call, except that this is passed as a normal parameter instead of as the value that the function was accessed on. This is similar to how general-purpose utility functions work: instead of calling array.map(callback), you use map(array, callback), which avoids mutating Array.prototype, and allows you to use map with array-like objects that are not arrays (for example, arguments).

Take Array.prototype.slice(), for example, which you want to use for converting an array-like object to a real array. You could create a shortcut like this:

const slice = Array.prototype.slice;

// ...

slice.call(arguments);

Note that you can't save slice.call and call it as a plain function, because the call() method also reads its this value, which is the function it should call. In this case, you can use bind() to bind the value of this for call(). In the following piece of code, slice() is a bound version of Function.prototype.call(), with the this value bound to Array.prototype.slice(). This means that additional call() calls can be eliminated:

// Same as "slice" in the previous example
const unboundSlice = Array.prototype.slice;
const slice = Function.prototype.call.bind(unboundSlice);

// ...

slice(arguments);