loading...

A Guide to Rest and Spread: Part 2

guin profile image Angelika Jarosz ・4 min read

What does ... mean in JavaScript? (2 Part Series)

1) A Guide to Rest and Spread: Part 1 2) A Guide to Rest and Spread: Part 2

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!

What does ... mean in JavaScript? (2 Part Series)

1) A Guide to Rest and Spread: Part 1 2) A Guide to Rest and Spread: Part 2

Posted on by:

guin profile

Angelika Jarosz

@guin

I love to create responsive data driven web apps with intuitive user experiences. When not writing code, I spend my time immersed in dance, aerial arts, and learning spoken languages.

Discussion

markdown guide
 

Thank you very much, Angelika! Your explanation is very clear, with well understandable examples.
I wish you could find a great job ;)
Have a good week end!

 
 

Great job and excelent examples. Thank you for sharing it with the community

 
 

A well-written article with great examples! Your explanation is easy to understand and doesn't skip small but important details.

 

Thank you! Glad you found it easy to understand : )