JavaScript Functions - Part 2: Call and Apply

Functions are first class objects, which gives them full access to properties and methods. Three key methods of the Function object are call, apply, and bind. These methods allow us to reuse functions, simplify the passing of arguments, and even lock in the value of this.

In the following post, we will cover call and apply, while a follow up will talk about bind. Often these three methods are combined in the same discussion, mainly due to each being a key method of the Function object, not necessarily because they are linked. Two of these, call and apply are similar, so let’s dive in and get to some definitions and examples.

Definitions:

  • call – method of the Function object that invokes a function with a specified this value and individual arguments
  • apply – method of the Function object that invokes a function with a specified this value and an array of arguments

call and apply

  • Executes the current function immediately and returns the result of the action
  • Allows you to specify the value of this
    • Note: if the value of this is not defined, the global (window in the browser) object will be used

So let’s say I have an awesome function:

function awesomeFunction (awesomeValue) {
  console.log('Everything is %o', awesomeValue);
}

We can invoke this function our standard way as outlined here

awesomeFunction('Awesome'); //Everything is awesome

We can also use call to invoke our function

awesomeFunction.call(null, 'Awesome'); //Everything is awesome

or use apply

awesomeFunction.apply(null, ['Awesome']); //Everything is awesome

Now let’s break this down a little bit as there are a few things going on

1) Why did we pass in null?
We passed in null as the first parameter to call and apply is the thisValue. In our case, we are not referencing this (it is not used at all in our function) so we can pass in null. We will explore using the thisValue parameter in the later examples when we chain constructors below.

2) What’s going on with the second parameter?
These are the parameters to our function. In the case of awesomeFunction there is only one parameter, the awesomeValue that we will log. As call takes individual parameters and apply takes an array, we pass the parameters in accordingly.

So what if we had a function that took multiple parameters, how might that look?
Glad you asked, let’s try that out.

function add(a, b) {
  return a + b;
}

Now let’s invoke the standard way

add(5,10) //15;

How would this look with call?

add.call(null, 5, 10) //15;

And apply?

add.apply(null, [5,10]) //15;

So the genereal form of each is:
call

myFunction.call(thisValue, param1, param2, param3, ... paramN);

apply

myFunction.apply(thisValue, [param1, param2, param3, ... paramN]);

Great, but ummm, why would I ever want to do this? In the example you showed, isn’t the standard way less involved, less characters to type, and doesn’t require me to pass in some weird null parameter.
Why yes, the example was a simple one to show the general form of each function, you know walk before we can run and all that. Now that we have the basic syntax, let’s go further. Newness coming right up…

Benefits of call and apply
These functions allow us to reuse (borrow) functions – “you have some cool functionality, may I use it”?

const upper = "HELLO WORLD";
const lower = String.prototype.toLowerCase.call(upper);

Simplifying function calls
Say I have an array of numbers and I want to find the highest number. I might make a function similar to the one below

const numbers = [5,8,3,9,11,2];

function getMax() {
  let max = numbers[0];
  for (let i = 1; i < numbers.length; i++) {
    if (numbers[i] > max) {
      max = numbers[i];
    }
  }
  return max;
}

So how might we leverage our newfound tools to simplify this code? We can do so by utilizing apply.

const numbers = [5,8,3,9,11,2];

function getMax() {
  return Math.max.apply(null, numbers);
}

Ok, but what else can we do?
Additionally, These methods allow us to utilize inheritance in the form of “parent” function calls (similar to the above point, but utilized frequently for “class” based design patterns in JavaScript)

/**
 * Example illustrating usage of call and apply to utilize "parent"
 * function calls and implement inheritance-like features
 */

/**
 * Player function used to create a new player
 * @param {String} name - name of the player
 * @param {Number} number - the number on the player's jersey
 */
function Player(name, number) {
  this.name = name;
  this.number = number;
}

/**
 * Player function used to create a new point guard
 * @param {String} name - name of the player
 * @param {Number} number - the number on the player's jersey
 */
function PointGuard(name, number) {
  //note usage of call
  Player.call(this, name, number);
  this.position = 'PG';
}

/**
 * Player function used to create a new shooting guard
 * @param {String} name - name of the player
 * @param {Number} number - the number on the player's jersey
 */
function ShootingGuard(name, number) {
  //note usage of apply
  Player.apply(this, arguments);
  this.position = 'SG';
}

const iverson = new PointGuard('Allen Iverson', 3);
const kobe = new ShootingGuard('Kobe Bryant', 24);

console.log(`${iverson.name} ${iverson.number} ${iverson.position}`);  //Allen Iverson 3 PG
console.log(`${kobe.name} ${kobe.number} ${kobe.position}`);           //Kobe Bryant 24 SG

Link to repl example

What about other positions and players?
I leave that as an exercises for the reader/voice in my head to code up.

Why/when would you use these functions?

  • call/apply
    • you want to reuse a previously defined function, such as for inheritance
    • you want to borrow another function’s capabilities
  • apply
    • you want to pass in an array of parameters vs specifying each parameter individually

Conclusion

Phew, not so bad, right? Right! In this post we have defined call and apply, provided examples that show how to use each method, and outlined key benefits. By using call and apply we can reuse an object’s methods, simplify function calls, and borrow constructors to create “class” based design. How might you be able to utilize call and apply in your programs?

Additional Resources

  • Great definitions with examples from Mozilla on call and apply
  • TL;DR overview of call/apply/bind from codeplanet
  • An in depth walkthrough by JavascriptIsSexy on all call, apply, and bind

Updated: