JavaScript: Spread and Rest operators

Spread and Rest - How it works and how to use them

by Tibor Kopca Date: 05-04-2021 javascript programming code webdev


In today’s article we are going to talk about one of the features of the ES6 version(ECMAScript 2015) of JavaScript which is Spread operator as well as Rest operator.
These features may be very useful when developing and working with front-end frameworks. We will explain how you can use it in practice when copy and merge arrays and object literals, insert data, with the benefits of making your code cleaner. Let's get into it and see how it works.

Spread Operator Definition and Syntax

Spread operator looks like three dots (...) and what it does, it takes the group in expression and it tries to “spread” it to multiple values.
You can take the elements of an existing array to a new array. When we have an iterable like for example an array with multiple values, it expands the values in that array into individual elements.
It is mostly used in the variable array where there is more than one value are expected.

var variable = [...value];

There are basically 3 occasions where you can use spread - In array literals, object literals and in function calls.
Also it can be used  to make copies of objects, so let's start with that.


Copy of an array or object

Making copies of non-primitives can be tricky. If you copy a primitive, like a number or a string, you will create a real copy, but with objects it's different.
Lets create an array with 3 elements. Then we make a shallow copy of that array using spread operator and the third array is a new array, but basically it's the same array as array1 - that's because when you assign array1 to be array3, the reference to the array1 is copied, not the values themselves.

That’s JavaScript copy by reference. When we make changes to the array1, also array3 will be altered, because the reference of the variable is the same place in memory. With the spread operator, we actually create a new array completely - the values will be copied and JS will handle this new object as a separate, like newly declared entry to the memory. By making changes to the new array2, the original would not be affected. This is called deep copy.

let array1 = ['h', 'e', 'y'];
let array2 = [...array1];
let array3 = array1
 
console.log(array2); //Array(3) [ "h", "e", "y" ]
array1.shift();
console.log(array1); //Array [ "e", "y" ]
console.log(array2); //not changed - Array(3) [ "h", "e", "y" ]
console.log(array3); //Array [ "e", "y" ] 

Note: Spread only goes one level deep when copying an arrays or objects, it doesn't perform a deep copy of nested data structures. (for that you would need const myClone = JSON.parse(JSON.stringify(objToClone))
This next example will show creating a copy of an object.

const myName = {
    firstName :'Tibor',
    middleName : '',
    lastName : 'Kopca'
}
const newName = {...myName}         //using spread we copy the object
newName.middleName = 'Tiburon'          //we add new atribute to copied object
console.log("old name was :"+myName.firstName+" "+myName.middleName+" "+myName.lastName)
//old name was :Tibor  Kopca
console.log("new name is :"+newName.firstName+" "+newName.middleName+" "+newName.lastName)
//new name is :Tibor Tiburon Kopca

Spread in array literals

Spread operator can be used in many cases, like when we want to expand,copy,concat the first object.
We can effectively merge two or more iterables without the need of the concat method.
Here is some example of the use when you need to add elements from array1 and array2 together, combining them into one.
Note: for the large data using spread operator will result slower compared to the native concat() method.

let array1 = [1,2,3,4,5,6];
let array2 = [7,8,9];
let arrayConcat = array1.concat(array2);
console.log(arrayConcat); //Array(9) [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
let arraySpread = [...array1, ...array2]; //Combining both arrays into one
console.log(arraySpread); //Array(9) [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

Likewise if we want to expand one array for more values:

let arrayExpanded = [...array2, 10, 11];
console.log(arrayExpanded); //Array(5) [ 7, 8, 9, 10, 11 ]

Or we can concatenate string arguments. Notice the difference in two last rows.

console.log("Hello", "Ma-no.org"); //Hello Ma-no.org
//concat() text
let text = ["Hello", "world", "!"];
console.log(text); //Array(3) [ "Hello", "world", "!" ]
console.log(...text); //Hello world !

Here we can see that strings are also iterable.

console.log(..."VICTORY!"); // V I C T O R Y !

Here is another example of concatenated arrays into one big array.
Order of adding the arrays does matter in this case.

let pets = ['cat', 'dog', 'bird'];
let kids = ['Peter', 'Suzan'];
const fullfamily = [...kids, ...pets];
console.log(fullfamily); //Array(5) [ "Peter", "Suzan", "cat", "dog", "bird" ]

Spread in Function calls

Let’s look at some examples when working with math object. Here we will for example find the minimum from a comma separated list of arguments - the numbers 0 to 4, and the lowest number is ‘0’. With no arguments it will be infinity, etc.
But with the list of numbers in the array it wont work and will return NaN. Now we can make use of the spread operator, which allows us to pass every number in the array in the Math function as individual arguments.

console.log(Math.min(0,1,2,3,4));    //0
console.log(Math.min());            //infinity
 
let arrayNumbers = [0,1,2,3,4];
console.log(Math.min(arrayNumbers)); //NaN
 
let arrayNumbersWithSpread = [0,1,2,3,4];
console.log(Math.min(...arrayNumbersWithSpread)); //0

Array to arguments


Now this next thing is interesting. When you use spread to access content of an iterable, it will return the content.
Instead of passing every argument, you can pass in an array with all the arguments. The result will be the same as if you would pass all arguments one by one.

const myTeam = ['Ivet', 'Ismael', 'Luigi', 'Silvia']
function printTeam(person1, person2, person3){
    return document.write(`Ma-no has the best team with - ${person1}, ${person2}, ${person3}.`)
}
printTeam(...myTeam)

Object literals and Spread

Just like with arrays, we can use spread to combine and copy objects, it's the same principle.
Let's say we have object holding some name, using spread followed by object name will access the property (content) of the object and log it out like this:

const myName = {
    firstName :'Tibor',
    middleName : '',
    lastName : 'Kopca'
}
console.log({...myName}) //Object { firstName: "Tibor", middleName: "", lastName: "Kopca"
const newName = {...myName}     //using spread we copy the object
newName.middleName = 'Tiburon' //we add new atribute to copied object
console.log("old name was :"+myName.firstName+" "+myName.middleName+" "+myName.lastName)
// old name was :Tibor  Kopca
console.log("new name was :"+newName.firstName+" "+newName.middleName+" "+newName.lastName)
// new name was :Tibor Tiburon Kopca

Of course just like by arrays the spread operator can be used to concatenate objects. As spread were shorthand for the Object.assign() method..

const obj1 = {title : 'The Wall'}
const obj2 = {author : 'Pink Floyd'}
const music = {...obj1, ...obj2}
console.log(music) //Object { title: "The Wall", author: "Pink Floyd" }

Destructuring

First start with destructuring, because this leads directly to the rest operator. As the name suggests, destructuring is to take an object or an array and convert it into smaller objects or smaller elements with fewer variables. In the second part we have a function that returns sum and deduction of 2 numbers. We can destructure its return into 2 variables like you see down here.

let letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
const [element1, element2, element3] = letters
console.log(element1, element2, element3) //a b c
 
function addAndDeduct(num1, num2){
    return [num1 + num2, num1 - num2]   //this will return first number in array summed and the second deducted
}
const [sum, deduct] = addAndDeduct(1,5)
console.log(sum)        //this will print variable sum which is 6
console.log(deduct)     //-4

Rest Operator

Very shortly we will mention the rest operator, which looks exactly like the spread operator. It allows us to represent an indefinite number of arguments as an array - basically collects all remaining arguments of a function into an array. It functions similar to the spread operator, but there is a slight difference. Only the last parameter can be a "rest parameter". Lets see some examples of the use, and notice the result is an array. In this example, the first argument is mapped to a and the second to b, so these named arguments are used as normal. However, the third argument, ‘args’, will be an array that contains the 3rd, 4th, 5th, 6th ... nth — as many arguments that the user includes.

function useRest(a, b, ...args) {
  console.log(args);
}
useRest(1,2,3,4,5); //Array(3) [ 3, 4, 5 ]

So the three dots ( ...) represent both the spread operator and the rest parameter. Here are the main differences: The spread operator unpacks elements. The rest parameter packs elements into an array. The rest parameters must be the last argument of a function. However, the spread operator can be anywhere.

function foo(a, ...rest, b) {
 //will produce error
}

Conclusion

In this tutorial we learned about JavaScript spread and rest operators and how to handle them.

Lastly we advise checking for browser compatibility at MDN web docs if you liked this article and you're up to using spread operator in practice.

That's pretty much it, we hope you enjoyed the article.

Image from Pixabay

 
by Tibor Kopca Date: 05-04-2021 javascript programming code webdev hits : 7402  
 
Tibor Kopca

Tibor Kopca

From tinkering with computers as a teenager, through a career in datacenter he stepped into web development with full force and started coding. Absorbs all information like a sponge.
Fan of aerospace, engineering, information technologies and watches.

 
 
 

Related Posts

What are React Hooks and what problems they solve

Working with React, - and before the release of Hooks in version 16.8 -  there was always the possibility to create components in three different ways based on a number of…

Flattening arrays in JavaScript

When we are handling arrays that are arrays or have multiple dimensions it can be very useful to know how to flatten arrays in JavaScript. That is to say, to…

How to populate an array with random numbers in JavaScript

Some of you might think that what we explained in the article on how to populate an array with numbers, apart from the didactic part, would not have much applicability…

How to populate an array with numbers in JavaScript

Populate an array with numbers in JavaScript The first step is to initialise the array. So today we are going to see a simple way to do it and see how…

Top Javascript Libraries and Frameworks Part 2

What are JavaScript frameworks?   JavaScript frameworks are application frameworks that allow developers to manipulate code to meet their particular needs. Web application development is like building a house. You have the option…

How to Send Email from an HTML Contact Form

In today’s article we will write about how to make a working form that upon hitting that submit button will be functional and send the email (to you as a…

Top JavaScript libraries and frameworks part 1

JavaScript libraries and frameworks make it easy to develop websites and applications with a wide variety of features and functionality, all with dynamic, flexible and engaging features. According to a 2020…

Looping through a matrix with JavaScript

We were already talking about how to multiply arrays in JavaScript and we realised that we had not explained something as simple as traversing an array with Javascript. So we…

How to multiply matrices in JavaScript

It may seem strange to want to know how to multiply matrices in JavaScript. But we will see some examples where it is useful to know how to perform this…

JavaScript Formatting Date Tips

Something that seems simple as the treatment of dates can become complex if we don't take into account how to treat them when presenting them to the user. That is…

How to make a multilingual website without redirect

Today, we're going to talk about how to implement a simple language selector on the basic static website, without the need of any backend or database calls or redirection to…

Starting with Bootstrap-Vue step by step

Today we will show you how to use BootstrapVue, describe the installation process and show basic functionality. The project’s based on the world's most popular CSS framework - Bootstrap, for building…

We use our own and third-party cookies to improve our services, compile statistical information and analyze your browsing habits. This allows us to personalize the content we offer and to show you advertisements related to your preferences. By clicking "Accept all" you agree to the storage of cookies on your device to improve website navigation, analyse traffic and assist our marketing activities. You can also select "System Cookies Only" to accept only the cookies required for the website to function, or you can select the cookies you wish to activate by clicking on "settings".

Accept All Only sistem cookies Configuration