JavaScript Spread and Rest Operator

JavaScript

JavaScript Spread and Rest Operator

Examples of using the spread and rest operator on JavaScript Objects and Arrays

The release of ES2015 brought a host of new features to JavaScript to allow us to write more concise and declarative code. One of the powerful new features is the spread and rest operators, three dots that can be used to spread and collect data in Objects and Arrays. We can take advantage of ES2015 and later updates to ECMAScript by using a transpiler like Babel to convert our code to ES5 compliant JavaScript.

Convert Function Arguments to an Array

With ES2015 arrow functions there is no arguments Object available within the function. In strict mode, the arguments Object is created and initialised with the same values as the named arguments, but changes to either the arguments Object or the named arguments aren't reflected in one another. In non-strict mode, modifying a value in the arguments Object modifies the corresponding named argument. Its hard coded name makes difficult to access arguments of an outer function in an inner one (which defines its own arguments). The arguments Object also appears array like but does not have common array methods except length.

If you want to pass an unknown number of arguments to your function, or by pass the arguments Object you can use the rest operator to collect the extra arguments:

function example (one, two, ...collect) {
  const collectIsArray = Array.isArray(collect);
  const argumentsIsArray = Array.isArray(arguments);
  console.log({collect, collectIsArray, argumentsIsArray});
}
example('a', 'b', 'c', 'd') // { collect: [ 'c', 'd' ], collectIsArray: true, argumentsIsArray: false }

As long as we use the rest operator as the last parameter in the function declaration we can use it along with other individual parameters like the example above, or it can collect all the arguments by using it as the only parameter on a function. We can also use Array methods on collect now to iterate over it.

Convert Nodelist to an Array

Anther common task is using [querySelectorAll] to select particular elements in the DOM. This returns a Nodelist which resembles an Array but does not have all the methods available to an array. We can spread the Nodelist into an array when we declare it like this:

const paragraphs = [...document.querySelectorAll("p")];

Copying Arrays

Copying of an Array is a frequent task, something we've used Array.prototype.slice to do in the past, but we can now use the spread operator to get a copy of an Array:

const arr = ['a','b','c'];
const arrTwo = [...arr];

Important: any Objects within the array will copy the reference to the Object in the original Array, so both arrays references point to the same Object.

We can use the spread operator to spread the Array anywhere into a new Array:

const arrThree = ['e', 'f', 'g'];
const joined = [...arr, 'd', ...arrThree];
console.log(joined); // [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ]

Destructing Objects and Arrays

Destructing assignments is a powerful way to manipulate Objects and Arrays, frequently used in React apps when passing props. The rest operator provides you with a good way to remove a property from an Object in an immutable way:

const user = {
  city: "Mudgee",  
  email: "test@example.com",
  password: "password",
};

const { password, ...toTransmit } = user;
console.log(toTransmit);  // { city: 'Mudgee', email: 'test@example.com' }

The same thinking can be very useful with Arrays too:

const drinks = ['water', 'lemonade', 'cola', 'tea'];  
const [first, ...lessPopular] = drinks;
console.log(first);      // => 'water'  
console.log(lessPopular); // => ['lemonade', 'cola', 'tea'] 

Conclusion

With Ecma foundation releasing incremental updates to ECMAScript annually, keeping up to date with new features can make our code cleaner and easier for other developers to interpret. If you have further information to add, contact me via Twitter @rhysonrails or click the email link below to send me an email.