My last article covered spread syntax and Object.assign in detail, but glossed over rest parametersin the interest of time. I do, however, feel they deserve a closer look.

Let’s begin at the trusty MDN Docs:

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

That last part, “as an array”, is interesting, because before ES6 arrow functions, we used the arguments object. It was array-like, but not actually an array.

Example:

function returnArgs() {
  return arguments;
}

1*Xuhn5NvMtl3Mev2FqL-oug

We see arguments has indices, so it’s loop-able:

function loopThruArgs() {
  let i = 0;

  for (i; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}

1*jU_wgPi5ILJrOQ7F0J8sUA

But it’s not an array.

1*KNeT3_DX6pQE3TWkjzJiMg

Let’s contrast that with a function using rest parameters:

es6Params = (...params) => {
  console.log('Array?', Array.isArray(params));
  return params;
};

1*cPEtXM-jUWC3oDsCHU2keg

It’s just an array, meaning we can use any of the Array methods on it!

Let’s write a function that doubles and sums every parameter you give it.

double = (x) => x * 2;
sum = (x, y) => x + y;

doubleAndSum = (...numbers) => numbers.map(double).reduce(sum, 0);

1*Hdk9NP-ZGteTef7v5RPBEg

And you can name as many parameters as you want in your function before using rest.

someFunction = (a, b, c, ...others) => {
  console.log(a, b, c, others);
};

1*NZVvRUAyRffRtcckUIPdLA

But it has to be the last one specified, since it captures the rest of your arguments. ?

1*xjYSLt00rbmHdUtBYWUPMg

I think we know what’s happening under the hood, but let’s be thorough. Check out babeljs.io/repl, where you can write ES6+ code and have it transpiled into ES5 in real-time.

1*qYBa9yW0izOhXaTfP8IBKw

That’s a neat little function, let’s expand it and add comments.

someFunction = function someFunction() {
  var _len = arguments.length;

  // create an array same length
  // as the arguments object
  var args = Array(_len);
  var i = 0;

  // iterate through arguments
  for (i; i < _len; i++) {
    // assign them to
    // the new array
    args[i] = arguments[i];
  }

  // and return it
  return args;
};

Since Babel wrote an old-school function for us, it can access the arguments object! arguments has indices and a .length property, which is all we need to create a perfect clone of it.

This is why we can use Array methods like map, filter, reduce on rest parameters, because it creates an Array clone of arguments.

Have fun rest-ing!