Rest Arguments in ES5

The ES2015 specification introdues support for rest parameters (also known as spread arguments or variadic arguments). Sadly, not everyone is currently able to use ES2015+ syntax and features, typically due to browser support constraints. Here’s a solution for those of you stuck using ES5.

The Code

Let’s look at an example of what we’d like to implement using ES2015.

function example (foo, ...bar) {
  /* ... */
}

And here is an equivalent operation in ES5.

function rest (args, start) {
  return Array.prototype.slice.call(args, start || 0);
}

function example (foo) {
  var bar = rest(arguments, 1); // array of all arguments after "foo"
  /* ... */
}

Why It Works

Javascript functions automatically receive all of their arguments in an iterable object called arguments. Though the function is iterable, it’s not an actual array, meaning you miss out on array methods like .map() and .forEach().

To convert arguments to an array, we can coerce it by setting it as the context for Array.prototype.slice() by using .call(). This works because .slice() treats the contextual value as iterable value, rather than an actual array.

The first argument of .call() is this desired context of the function we’re calling. The subsquent arguments are 1-to-1 with how we’d typically invoke the function. This means that the next argument we want is the index we wish to start slicing from.

0 would result in slicing from the beginning of the array, resulting in all arguments being presented in the returned array. 1 would start from the first argument back, and so on.