We have seen how a rest parameter can help the handling of a variable number of function arguments. What about the other way around? Can we turn an array into a series of function arguments? Apparently, ECMAScript 6 defines a new type of operator called the spread operator which does exactly that.
Let us review again our previous example with a supplier truck and a grocery store. Assuming the API of the store accepts a variable number of items for a particular category:
store.add('fruit', 'apple');
store.add('dairy', 'milk', 'cheese', 'yoghurt');
store.add('pastries', 'donuts', 'croissants');
We assume that these delicious items are stored in some boxes, each box happens to be an array:
var dairyBox = ['milk', 'cheese', 'yoghurt'];
A possible solution (out of many others) to invoke store’s add
function with the items in the above array is by using Function.prototype.apply. Since we need to pass the food category as the first argument, a little bit dancing with Array.concat is necessary:
store.add.apply(store, ['dairy'].concat(dairyBox));
For the untrained eyes, it looks like one of those magical JavaScript incantations.
With ECMAScript 6, this can be simplified by using ...
prefix in a spread expression (section 11.2.5, ES6 draft Rev 14).
store.add('dairy', ...dairyBox);
That dairyBox
array is simply spread to fill the remaining argument list.
Obviously, one possibly common place where spreading is always useful is when dealing with arrays. We know that push
accepts multiple number of arguments. The implementation of add
function originally looks like:
store.add = function(category, ...items) {
items.forEach(function (item) {
store.aisle[category].push(item);
});
};
which can be further shortened to become something like the following fragment. Nifty, isn’t it?
store.add = function(category, ...items) {
store.aisle[category].push(...items);
};
(This is of course unnecessary if you choose to change the API to simply accept a single array for the items, instead of a rest parameter combined with spreading).
The use of a spread operator can lead to a different way of combining arrays:
var x = [1, 2];
var y = [3, 4];
x.push(...y); // x is [1, 2, 3, 4]
What other tricks do you have in mind once you have the spread operator ready to abuse?