Rest Syntax

Happy July! To start off this month, I'm tackling a blog post that I've kind of been dreading: Rest Syntax! I know I'm not the only one, but this one has been really confusing for me to wrap my head around since I first encountered it, and this is for a few reasons. For one thing, it's syntactically identical to the Spread Operator except for the context you use it in. I'm also not sold on the name, because I had already mentally filled the "JavaScript Rest" terminology space in my brain with a reference to RESTful APIs. But! I'm hoping that writing about it will help to demystify what's going on here, and what the difference between ...spread and ...rest is, but I fully anticipate that in conversation (and probably parts of this blog) I might still get the two confused. Okay, enough preamble.

Usage of Rest Syntax breaks down nicely into two contexts:

  1. Working with a function that can take an unknown number of arguments
  2. Destructuring an array where certain array items need to be assigned to specific variables, and the rest can be grouped together

Let's look at each context.

Function Arguments

Let's say we wanted to have a function that can take an unknown quantity of arguments and do some work with it. I think MDN's basic example of a reducer function that produces a sum works nicely. We need to take x number of values and add them up, but that could be 2 values or 200. Unfortunately, prior to ES6 there wasn't a concise way to do that. Now, with Rest parameter syntax, there is.

function sum(...numbers) {
  const sum = numbers.reduce((number, accumulator) => {
    return number += accumulator;
  }, 0);
  return sum;
};

console.log(sum(1, 2, 3));
// expected result: 6
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
// expected result: 55

The magic comes in with the ...numbers syntax within the function arguments. Typically I would reach for an array to work with, like const numbers = [1, 2, 3]; and pass that as the argument, but that's not always the kind of data we're working with, and that's no way to live.

However, ...rest also works with Array Destructuring.

Array Destructuring

Making a good playlist is a hard thing to do. You have to get the tone right for your audience, know what songs work with one another, hammer down a certain track order, and so on. Say you had a list of ten songs you wanted to put on a playlist for someone you cared about. You're mainly concerned with what the first three songs are. The first one has to be a banger, to draw the listener in. The second one has to be really groovy. The third one can be more heartfelt. Then the seven songs after that can all just be stuff you really like.

const playlistSongs = [
  {
    artist: 'Absolutely Free',
    song: 'Currency'
  },
  {
    artist: 'Carly Rae Jepsen',
    song: 'Too Much'
  },
  {
    artist: 'Moon Racer',
    song: 'Song of the Mogwai'
  },
  {
    artist: 'Yaeji',
    song: 'Feel It Out'
  },
  {
    artist: 'Marina',
    song: 'Handmade Heaven'
  },
  {
    song: 'Chemical Trail',
    artist: 'Gothic Tropic'
  },
  {
    artist: 'The Royalty',
    song: 'Bottle Breaker'
  },
  {
    artist: 'Roky Erikson',
    song: 'Two Headed Dog'
  },
  {
    artist: 'Baynk',
    song: 'Come Home'
  },
  {
    artist: 'Japanese Breakfast',
    song: 'The Body is a Blade'
  }
];

const [banger, groovy, heartfelt, ...otherStuffILike] = playlistSongs;
console.log(banger);
// expected result: { artist: "Absolutely Free", song: "Currency" }
console.log(groovy);
// expected result: { artist: "Carly Rae Jepsen", song: "Too Much" }
console.log(heartfelt);
// expected result: { artist: "Moon Racer", song: "Song of the Mogwai" }
console.log(otherStuffILike);
// exptected result:
// [
//   {
//     artist: 'Yaeji',
//     song: 'Feel It Out'
//   },
//   {
//     artist: 'Marina',
//     song: 'Handmade Heaven'
//   },
//   {
//     song: 'Chemical Trail',
//     artist: 'Gothic Tropic'
//   },
//   {
//     artist: 'The Royalty',
//     song: 'Bottle Breaker'
//   },
//   {
//     artist: 'Roky Erikson',
//     song: 'Two Headed Dog'
//   },
//   {
//     artist: 'Baynk',
//     song: 'Come Home'
//   },
//   {
//     artist: 'Japanese Breakfast',
//     song: 'The Body is a Blade'
//   }
// ]

In this destructuring context, ...rest syntax works magically to separate the last 7 songs from the 3 that you really care about at the beginning of the array.

From MDN: The rest parameter syntax allows us to represent an indefinite number of arguments as an array.

See more examples and documentation here.

More Spread Syntax

Read more about Spread Syntax, Destructuring, and Rest here:

  1. Array Spread
  2. Function Spread
  3. Object Spread
  4. Array Destructuring
  5. Object Destructuring
  6. Rest Syntax