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 : 8138  
 
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

Difference between arrow and normal functions in JavaScript

In this tutorial we are going to see how arrow functions differ from normal JavaScript functions. We will also see when you should use one and when you should use…

JavaScript Arrow functions: What they are and how to use them

In this article we are going to see what they are and how to use JavaScript Arrow Functions, a new feature introduced with the ES6 standard (ECMAScript 6). What are Arrow…

How to insert an element into an array with JavaScript

In this brief tutorial you will learn how to insert one or more elements into an array with JavaScript. For this we will use the splice function. The splice function will not…

What is the difference between primitives types and objects in JavaScript?

In this short tutorial we are going to look at the differences between primitive types and objects in JavaScript. To start with, we're going to look at what primitive types…

How to get DOM elements with JavaScript

When you access any element of the DOM, it is usual to save it in a variable. This is something that at first might seem very simple, but if you…

How to reverse an array in JavaScript

In this tutorial we are going to see how you can change the order of the elements of an array so that they are inverted. You could use a loop…

How synchronize the scroll of two divs with JavaScript

In case you have two divs of different sizes you may sometimes want to scroll both at the same time but at different speeds depending on their size. For example,…

How to use the codePointAt method in JavaScript

The JavaScript codePointAt method has more or less the same function as the charCodeAt method, used to get the 16-bit Unicode representation of the character at a certain position in…

How to check if a value is a number in JavaScript

In this short tutorial we are going to look at the various methods that exist to find out if a value is a number in JavaScript.   1. Using the isNaN() function   One…

How to use the charCodeAt method in JavaScript

The charCodeAt method is accepted by strings in JavaScript, returning the 16-bit Unicode code of the character at the position we pass as a parameter to the method. The charCodeAt method…

How to use the charAt method in JavaScript

The charAt method is accepted by strings in JavaScript, returning the position of the character passed as a parameter within the string. If the string contains multiple occurrences of the character…

Strings in JavaScript: What they are and how to use them

In this tutorial we are going to explain what strings are and how they are used in JavaScript. The tutorial is intended for people who are learning to program in…

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