In More Useful Function Patterns: Multiple Arguments I wrote about rest parameters, a new ES6 feature, that lets you define functions with an arbitrary number of arguments just like
params in C#.
The spread operator works sort of in an opposite way to the rest operator. Where the rest operator takes a variable number of arguments and packs them into an array, the spread operator takes and array and expands it into its compounding items.
Let’s find out how this new ES6 feature can help you write more readable code.
Use the Spread Operator to Seamlessly Concatenate Arrays
You can use the spread operator to easily concatenate arrays with each other. Let’s say that we want to collect our most terrible enemies for later reference. We have an array
knownFoesLevel1 and another array
newFoes with newly acquired enemies:
Since it’s easier to manage one collection than two, we want to merge these two collections within the same array. Where you would have used the
concat method in ES5:
1 2 3
In ES6 you can use the spread operator to achieve the same effect with a much clearer syntax:
1 2 3
You can even mix arrays and items:
1 2 3 4 5
Easily Apply With the Spread Operator
The spread operator offers you an alternative syntax to
Function.prototype.apply function to explicitly set the context (
this) in which a function is executed. At the same time, you learned how
apply expects an array of arguments as second parameter and how when the function is finally invoked each element within the array is passed as a separate argument to the original function.
Well spread let’s you call an arbitrary function with an array of arguments in a much better way than
Let’s say that you are working on a spell to command your minions with random actions because being too predictive is boring and you appreciate the wild factor. You express these random actions as arrays:
['minion1', 'action', 'minion2']
Let’s now say that you have a function of your own device where you want actions to be done viciously (looks like you are in a foul mood today):
1 2 3
Because the action is expressed as an array but the
performActionViciously function expects a separate series of arguments you need a way to adapt these two disparate elements. Prior to ES6 you would have used the
Where you would need to fill in the context in which the function will be executed (
this) for the
apply method to work.
With ES6 you can use the spread operator to easily perform an action:
1 2 3
No need to set the context (
this) in which the function is executed and the resulting code is much concise with the omission of
You may be asking yourself, why don’t I make the
performActionViciously function take an array as argument? Well, you could do that. But what happens when you have no control over the function being called?
Imagine that, instead of performing these actions viciously, you just want to log them. Because
console.log takes an arbitrary number of arguments and you have an array, you need some way to adapt the array to the expected signature. Again, prior to ES6 you would use
1 2 3
With ES6 and the spread operator you can simplify the code sample above as follows:
Another example in which the spread operator comes handy is when we want to extend an existing array with another array. In the olden days we would have written:
1 2 3 4 5
With the spread operator it would’ve been as easy as:
In summary, do you have some variable as an array and need to apply it to a function that takes separate arguments? Use the spread operator.
Converting Array-likes and Collections Into Arrays
Another interesting application of the spread operator is to convert array-like objects into arrays.
If you remember More Useful Function Patterns: Multiple Arguments, array-like objects are a special type of object that can be indexed, enumerated, has a length property but doesn’t have any of the methods of an array. Some examples of array-like objects are the
arguments object inside functions or the list of DOM1 nodes that result when using
Let’s imagine that we have a web-based user interface, a form, to help us create minions based on some characteristics that we can input manually (for even wizards can benefit from web interfaces). It could look like this:
1 2 3 4 5 6 7 8 9 10 11 12
When you click on the
Save button we want to store these values and create a new minion that will serve us for eternity. So we add an event handler that will be called when the form is submitted:
1 2 3 4 5
In the example above we use the
document.querySelector method to select the form element that represents the actual form and the
addEventListener method to register an event handler for the submit event of the form. Whenever the user clicks on the
Save button, the form will be submitted and the
saveMinion method will be called.
Now, the next step would be to extract the values from the inputs above. How can we go about that? Well we can select all the inputs within the form and extract their values.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
So we use the
form.querySelectorAll('input') method to select all input elements within the form. This method returns an array-like object of nodes. Because it has a length property we can use an simple for loop and a new array
values to collect the values. After that we can create our brand new minion with the extracted values.
But, is there a better way to do this? What about converting the
inputs array-like object to an array and using the helpful array methods instead of the for loop? Spread operator to the rescue!
1 2 3 4 5 6 7 8 9 10 11 12
By converting the array-like to an array using the spread operator we can use array functions such as
map and write more beautiful code.
map works just like LINQ’s
Select and let’s you perform transformations on each item of a collection. In this case we just transform a collection of elements into values.
In addition to array-like objects you can use the spread operator to convert any iterable object to an array. For instance a
Set (a collection of unique items):
1 2 3 4 5 6 7 8
Map (like a C#
1 2 3 4 5 6 7 8 9 10
Spread Lets You Combine New and Apply
The spread operator also lets you combine the
new operator with the ability to
apply arguments to a function. That is, the ability to instantiate objects using a constructor function while adapting an array of arguments into a constructor function that expects separate arguments.
Let’s continue the example from the previous section where we extracted the characteristics of our minion from an HTML form. The next natural step would be to create a new minion using those characteristics and the following constructor function:
1 2 3 4 5 6 7 8
If we were to use pure ES5 we would need to unwrap the values before we use them:
With ES6 we can combine
new with the spread operator to get a more readable code:
The full code example could look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
In the example above we first extract the values from the form and then we use them to create a
newMinion object by applying both the
new and the spread operators.
In this article you learned about the ES6 spread operator and how it works in sort of the opposite way to the rest operator. Instead of grouping separate items into an array, the spread operator expands arrays into separate items.
You learned how you can use it in many scenarios usually resulting in a more readable code: to easily concatenate arrays, as a substitute for
apply, to convert array-like objects and even other iterables to arrays and finally to combine the
new operator with
Have a awesome week!
More Articles in These Series
- Object Oriented Programming
- White Tower Summoning Enhanced: The Marvels of ES6 Classes
- Black Tower Summoning: Object Composition with Mixins
- Data Structures
- Functional Programming
- And more stuff to be shaped out:
- Asynchronous Programming
The DOM or Document Object Model is an object representation of a website where each HTML element is represented by an object called a node.↩