Rest Parameters — ES6 features-Part-2
By: Bhagirthi Jhamb
Tags: JavaScript, Arrays, ES6, Spread Operator, Rest Parameter

Rest Parameter uses the same syntax (…) like Spread operator, but the use and functionality is little different.

We know that many JavaScript built-in functions support an arbitrary number of arguments. For instance:

Math.max(arg1, arg2, ..., argN) – returns the greatest of the arguments.

– returns the greatest of the arguments. Object.assign(dest, src1, ..., srcN) – copies properties from src1..N into dest .

Here, we’ll try to do the same (make a function take any number of arguments). And also, how to pass arrays to such functions as parameters.

A function can be called with any number of arguments, no matter how it is defined. Like here:

const product = (a, b) => {

return a * b;

}



console.log( product(1, 2, 3, 4, 5) ); // 2

JavaScript engine will not throw any error because of “excessive” arguments. But of course in the result only the first two will be counted.

The rest of the parameters can be included in the function definition by using three dots ... followed by the name of the array that will contain them. The dots literally mean “gather the remaining parameters into an array”.

For instance, to gather all arguments into array args :

const productAll = (...args) => { // args is the name for the array

let product = 1; for (let arg of args) product *= arg;

return product;

} console.log( productAll(1) ); // 1

console.log( productAll(1, 2) ); // 2

console.log( productAll(1, 2, 3, 4, 5) ); // 120

Its same like, Math.min that computes the minimum of all the arguments it is given. If we want to write such function it will be some thing like this.

const min = (...numbers) => {

let result = Infinity;

for (let number of numbers) {

if (number < result) result = number;

}

return result;

}

console.log(min(4, 1, -2)); // -2

When such a function is called, the rest parameter is bound to an array containing all further arguments. If there are other parameters before it, their values aren’t part of that array. When, as in min, it is the only parameter, it will hold all arguments.

We can use a similar three-dot notation to call a function with an array of arguments.

let numbers = [5, 1, 7, 15, -3, 65, -31, 2, 21]; console.log(min(...numbers)); // -31

This “spreads” out the array into the function call, passing its elements as separate arguments. It is possible to include an array like that along with other arguments, as in min(9, …numbers, -3). Square bracket array notation similarly allows the triple-dot operator to spread another array into the new array.

console.log(min(9, ...numbers, -65)); // -65

We can choose to get the first parameters as variables, and gather only the rest.

Here the first two arguments go into variables and the rest go into yourName array:

const birthdaySong = (firstWord, lastWord, ...yourName) => {

console.log( firstWord + ' ' + lastWord ); // "Happy birthday" // the rest go into youName array

// i.e. titles = ["to", "Chloe"]

console.log( yourName[0] ); // "to"

console.log( yourName[1] ); // "Chloe"

console.log( yourName.length ); // 2

} birthdaySong("Happy", "birthday", "to", "Chloe");

Note: The rest parameters must be at the end. The rest parameters gather all remaining arguments, so the following does not make sense and causes an error:

function f(arg1, ...rest, arg2) {

// error // arg2 after ...rest ?!

}

Destructuring Rest Parameters

Rest parameters can be destructured, but for arrays only. This means we can unpack rest parameters to variables.

const add = (a, b, ...[c, d, e]) => {

console.log(c) // 3

console.log(d) // 4

console.log(e) // 5 return a + b + c + d + e

}; add(1, 2, 3, 4, 5); // 15

Notice how the parameters are saved as variables. We can do the same inside the function too.

const add = (a, b, ...rest) => {

console.log(rest); // [3, 4, 5]

console.log(...rest) // 3, 4, 5

}; add(1, 2, 3, 4, 5);

If we console.log the rest parameter with the dots, we get an array. But if we call it with three dots, we’re essentially unpacking the values into each separate number (not an array).

The “arguments” variable

There is also a special array-like object named arguments that contains all arguments by their index.

For instance:

function fullName() {

console.log( arguments.length ); // 2

console.log( arguments[0] ); // "Bhagirthi"

console.log( arguments[1] ); // "Jhamb" // it's iterable

for(let arg of arguments) console.log(arg); // "Bhagirthi", "Jhamb"

} fullName("Bhagirthi", "Jhamb",);

In old times, rest parameters did not exist in the language, and using arguments was the only way to get all arguments of the function.

But the downside is that although arguments is both array-like and iterable, it’s not an array. It does not support array methods, so we can’t call arguments.map(...) for example.

Also, it always contains all arguments. We can’t capture them partially, like we did with rest parameters. So when we need these features, then rest parameters are preferred.

If we access the arguments object from an arrow function, it takes them from the outer “normal” function. Here’s an example:

function f() {

let showArg = () => {

console.log(arguments[0], arguments[1], arguments[2]);

console.log(arguments)

}

showArg();

} f(1, 2, 3);

// 1, 2, 3

// [object Arguments]{

0: 1,

1: 2,

2: 3

}

As we remember, arrow functions don’t have their own this . Now we know they don’t have the special arguments object either.

Conclusion:

We can summarize Spread Operator and Rest Parameter as:

When we see "..." in the code, it is either rest parameters or the spread syntax. There’s an easy way to distinguish between them:

When ... is at the end of function parameters, it’s “rest parameters” and gathers the rest of the list of arguments into an array.

is at the end of function parameters, it’s “rest parameters” and gathers the rest of the list of arguments into an array. When ... occurs in a function call or alike, it’s called a “spread syntax” and expands an array into a list.

Use patterns:

Rest parameters are used to create functions that accept any number of arguments.

The spread syntax is used to pass an array to functions that normally require a list of many arguments.

Together they help to travel between a list and an array of parameters with ease.