Skip to content
Theory · Arrays · lesson 9 of 13

Rest parameters

Picture a bag at a checkout. The cashier does not know in advance how many items you will bring: two, ten or none at all. Everything that gets scanned goes into one bag, and at home you take the items out one by one.

Functions can be like that too. Math.max takes any number of arguments: both Math.max(3, 8) and Math.max(3, 8, 1, 9). How do you write your own function that can be passed any number of arguments? For that, three dots go into the parameter list:

JavaScript
function sum(...nums) {
    let total = 0;
    for (const n of nums) {
        total += n;
    }
    return total;
}

console.log(sum(1, 2, 3), sum(5), sum()); // 6 5 0

Let's go through it line by line:

  1. function sum(...nums) declares one parameter with three dots before its name.
  2. In the call sum(1, 2, 3), nums receives the array [1, 2, 3].
  3. The for…of loop walks through that array and adds the numbers into total.
  4. The call sum(5) gives an array of one element, and sum() gives an empty array, so the sum is 0.

The rest parameter

A parameter with three dots before its name is called a rest parameter. It receives every argument of the call that no ordinary parameter took. It is a real array: it has a length, you walk through it with for…of and read it by index.

This is where the bag analogy stops working. You can skip the bag, but a rest parameter is always there. With no arguments, nums is an empty array, not undefined, which is why sum() returned 0.

Parameters before it

Ordinary parameters can stand before the rest parameter. They get the first arguments, and the rest parameter collects what is left:

JavaScript
function describe(first, ...rest) {
    console.log(first, rest.length);
}

describe("a", "b", "c"); // a 2
describe("a"); // a 0

In the first call, first got "a", and "b" and "c" went into rest. In the second call no arguments were left for rest, and it is empty. This is how you write functions whose first argument is special and is followed by any number of values.

A rest parameter can only be the last one. Otherwise it would be unclear where its arguments end, and function f(...rest, last) does not run. Node and Chrome report:

TEXT
SyntaxError: Rest parameter must be last formal parameter

Collect and spread

In the lesson on references, three dots spread an array out into elements. Here they work the other way: they collect arguments into an array. One notation plays two roles:

  • in an array and in a function call, three dots spread elements out;
  • in a parameter list, three dots collect arguments.

The place tells the role: whether the three dots stand in the function's declaration or where an array is used. Interviewers often ask for the difference between rest parameters and spread syntax. The short answer: a rest parameter collects arguments into an array, while spread lays an array out into elements.

Common mistake

A ready array is passed to a function with a rest parameter:

JavaScript
const prices = [1, 2, 3];
console.log(sum(prices)); // ✗

There is no error, but the program prints 01,2,3, not 6. The array arrived as one argument, and nums became an array of one element, the array prices. Added to a number, the array turned into the string "1,2,3", and 0 got glued to it.

To pass the elements one by one, spread the array in the call: sum(...prices) returns 6.

Key points

  • The rest parameter ...nums collects the remaining arguments of a call into an array.
  • With no arguments, it is an empty array, not undefined.
  • The rest parameter stands last in the parameter list.
  • In a parameter list three dots collect arguments, and in an array or a call they spread elements out.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way