Rest Parameters In JavaScript

Functions that can take a variable number of arguments are called “variadic functions”.

Sounds fancy, right? I’m guessing even if you haven’t heard the term, you’re familiar with the concept. Functions like this are not uncommon.

Let’s look at a simple variadic function in JavaScript:

function sum() {
  let total = 0;

  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }

  return total;
}

sum(1); // returns 1
sum(1, 2, 3); // returns 6

Notice how sum has no parameters in its function header. Instead, it uses a special object called arguments. arguments acts kind of like an array, containing all the arguments passed to the function.

If you call sum with a single argument, arguments will have only that one. If you pass sum a dozen arguments, they’ll all show up in arguments.

Note: arguments is array-like, but it is not an actual array. You have to jump through some hoops if you want to do certain arrayish things with arguments. This can be annoying.

ECMAScript 2015 introduces some new syntax that can make variadic functions a little cleaner.

function sum(...numbers) {
  let total = 0;

  for (let i = 0; i < numbers.length; i++) {
    total += numbers[i];
  }

  return total;
}

No more arguments! We’ve added this new ...numbers parameter. This is a rest parameter. It says “I’m an (actual) array! Fill me up with all the arguments you were called with, from this point on in the list.”

In our new-and-improved sum, the rest parameter ...numbers captures all the arguments, because it’s first in the list. But a rest parameter could come at the end of a longer list of parameters, like so:

function foo(bar, baz, herp, derp, ...etc) {
  // ...
}

You can call foo with any number of arguments. The first four will be bound to bar, baz, herp and derp, and any additional ones after those four will fill up etc.

If you try to define a function with a parameter after a rest parameter, an error will occur.

For example:

function foo(...bar, baz) {}

In Chrome, this line throws an error: Rest parameter must be last formal parameter. This makes sense, because ...bar will capture all arguments in its array. No argument values could ever get into baz.