A Live Developer Journal

JavaScript Rest Parameter, Spread Operator and Default Values

Working through Rediscovering JavaScript: Master ES6, ES7 and ES8.

The Rest Parameter

The rest operator can be used as a placeholder for any number of arguments, like this: ...values. Using this as an argument in a function means you can pass in any number of arguments, that then get stored in an array called values. You can use array methods on the values array. Example:


const max = function(...values) {
return values.reduce((large, e) => large > e ? large : e, values[0]);
};

There must only be one rest parameter, and it must be the last one in the argument list if present. Rest parameters must also be empty arrays, we get an error if we try to give it a default value.

The Spread Operator

The spread operator looks exactly like the rest operator. While the spread operator gathers seperate values into an array, the spread operator breaks a collection into seperate values.

You can also use the spread operator to copy an object, modify it's properties and add new properties, whilst leaving the original object untouched:


const sam = { name: 'Sam', age: 2 };
console.log(sam);
console.log({...sam, age: 3});
console.log({...sam, age: 4, height: 100 });
console.log(sam);

Defining Default Values for Parameters

Advice in chapter not directly related to default values. The author sorted book titles by calling slice on the titles array before calling the sort method on in. This is because the sort method modifies the array it is called on, and it's bad practice to change the input given to a function.

In the following code example, we can use a named parameter to make our sort titles function sort in descending order as well as descending order.


const books = [
{ title: 'Who Moved My Cheese' },
{ title: 'Great Expectations' },
{ title: 'The Power of Positive Thinking' }
];

const sortByTitle = function(books, ascending = true) {
  const multiplier = ascending ? 1 : -1;

  const byTitle = function(book1, book2) {
    return book1.title.localeCompare(book2.title) * multiplier;
  };

  return books.slice().sort(byTitle);
}

console.log(sortByTitle(books));
console.log(sortByTitle(books, false));

Whenever you use default parameters, make them trail non-default parameters, to lessen the risk of them being undefined, like an argument called 'id'.

Hmm, I don't like the thought of mixing default and non-default parameters...

Expressions as Default Values

We can also use expressions as default argument values. That's pretty cool, though I'm not sure I like that either. Seems like something the body of the function should handle, though there might be use-cases where it does come in handy, just don't know those yet.