A Guide to Rest and Spread: Part 2
Angelika Jarosz
Posted on June 21, 2019
In Part 1, we briefly explained the difference between the rest parameter and the spread operator, and took a deep dive into the rest parameter. This post will continue on to take a dive into the spread operator. Here are the quick explanations from part 1 for a quick concept refresher:
Rest parameter: collects all remaining elements or arguments into an array.
Spread operator: allows iterables such as arrays and strings to be expanded into single arguments or elements. Object expressions will be expanded into another object.
Dive into the spread operator
In the previous post we saw the rest operator took some individual elements or arguments and collected them into one array. The spread operator essentially has the opposite function. It takes an iterable and expands it into multiple individual elements or arguments. Lets look at what this looks like in code and situations in which it is helpful to use.
Using the spread operator with:
- a string will give you the individual characters of the string
let aString = "spread string"
console.log(...aString) // s p r e a d s t r i n g
- an array will give you the individual elements in the array
let anArray = ["puppies", "kittens", 5, null]
console.log(...anArray) // puppies kittens 5 null
- an object will give you
let anObject = {"name": "Angelika",
"hairColor": "purple"}
console.log(...anObject) // Whoops we get a TypeError because anObject is not an iterable
console.log({...anObject}) // but we can spread it into another object and get
// {"name": "Angelika", "hairColor": "purple"}
Now that we understand the basics of what the spread operator does, lets look into how we would actually use it in our code.
Spread Operator Use Cases:
Copying arrays
If we want to make a copy of an array we can spread the array into another array literal like so:
let anArray = ["puppies", "kittens", 5, null]
let copyOfAnArray = [...anArray]
console.log(copyOfAnArray) // ["puppies", "kittens", 5, null]
Combining arrays
We can use the spread operator to combine arrays into a new array of all the individual elements like so:
let dogs = ["beagle", "corgi", "labrador", "poodle"]
let cats = ["persian", "ragdoll", "munchkin", "siamese"]
let animals = [...dogs, ...cats]
console.log(animals) // ["beagle", "corgi", "labrador", "poodle", "persian", "ragdoll", "munchkin", "siamese"]
If we didn't use the spread operator here we would get an array of two arrays.
animals = [dogs, cats]
console.log(animals)
// [["beagle", "corgi", "labrador", "poodle"], ["persian", "ragdoll", "munchkin", "siamese"]]
Passing elements of an array as arguments to a function
If we have an array of elements and we want to use those elements as the arguments to a function we can use the spread syntax instead of using the apply
method. In the fruits function below we have 3 parameters describing types of fruits. We have an args array whose elements we want to use as the arguments to the function. By using the spread operator on the args array, the elements will be passed in as the arguments to the function instead of the whole array as one argument.
function fruits(citrusFruit, stoneFruit, berry) {}
var args = ["lemon", "plum", "strawberry"]
fruits(...args)
// this is equivalent to calling fruits like so:
// fruits("lemon", "plum", "strawberry")
fruits(args)
// this is equivalent to calling fruits like so:
// fruits(["lemon", "plum", "strawberry"])
// which is not what we want
Using the above knowledge we can see how this can be useful with Math functions
let numbers = [10, 99, 5, 23, 4]
Math.min(...numbers) // 4
Math.max(...numbers) // 99
Object Spread
We can use spread to create a shallow copy of an object in another object and add a property to it without changing the original object. In the example below we have an object primitiveTypes
that has some examples of primitive types as key value pairs. We then create a new object dataTypes
that uses the spread operator to spread all the properties in primitiveTypes
into dataTypes, and we also add one more property.
const primitiveTypes = { "number" : 4,
"string": "pizza",
"boolean" : true,
"null": null,
"undefined" : undefined,
};
const dataTypes = {...primitiveTypes,
"array": ["stuff", "things"]
};
/* dataTypes object will be:
{ "number" : 4,
"string": "pizza",
"boolean" : true,
"null": null,
"undefined" : undefined,
"array": ["stuff", "things"]
}
*/
We can also merge two objects together easily using spread like so:
const obj1 = {"one": 1, "two" : 2}
const obj2 = {"three": 3, "four": 4}
const mergedObj = {...obj1, ...obj2}
// mergedObj will be
/* {"one": 1, "two" : 2, "three": 3, "four": 4} */
However we have to be careful when using spread with objects because we can override something we didn't mean to if we get the order wrong. Pay attention in the example below what happens to the value of the citrus
key in otherFruits
and differentFruits
depending on where we use the spread operator to spread the original fruits object.
const fruits = {
"citrus": "lemon",
"stone": "plum"
}
Order matters to determine if a key gets overridden!
const otherFruits = {
"citrus" : "lime",
"berry": "strawberry",
...fruits
}
console.log(otherFruits) // {citrus: "lemon", berry: "strawberry", stone: "plum"}
const differentFruits = {
...fruits,
"citrus": "lime",
"berry": "strawberry"
}
console.log(differentFruits) // {citrus: "lime", stone: "plum", berry: "strawberry"}
Hopefully you have come away with a better understanding of what the spread operator does in JavaScript and some of its use cases. As always one of the best ways to get a better understanding of the concepts is to get some practice using them!
If you have any questions, comments, or feedback - please let me know. Follow for new weekly posts about JavaScript, React, Python, and Django!
Posted on June 21, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.