Javascript: Spread and Rest Operators

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

by Tibor Kopca Date: 05-11-2020 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-11-2020 javascript programming code webdev hits : 5571  
 
 
 
 

Related Posts

Dark Mode on website using CSS and JavaScript

In today’s article we are going to learn how to build pretty much standard these days on the web pages and that is the alternative color mode and switching between…

A Java approach: The Cycles - Introduction

Hello everyone and welcome back! Until now, we have been talking about variables and selection structures, going to consider some of the fundamental aspects of these two concepts. Theoretically, to…

A Java Approach: Selection Structures - Use Cases

Hello everyone and welcome back! Up to now we have been concerned to make as complete an overview as possible of the fundamental concepts we need to approach the use…

A Java approach: boolean variables

The previous time, we talked extensively about Boolean variables, trying to outline the main operations that can be carried out at a practical level.  Of all the cases examined, we have…

A Java approach: condtional structures

Hello everyone and welcome back! The previous times we have introduced the concept of variable, trying to define some basic concepts about it.  However, some situations suggest that the concept of…

Hashmap: Overflow Lists

In this short series of articles we will go to see how it is possible to create the Hashmap data structure in C. In the implementation we're going to use the…

Javascript: what are callbacks and how to use them.

Today we are going to learn about a concept that is widely used in javascript and that is used quite a lot by today's frameworks, libraries, especially NodeJS. This is…

Data structures in Java - Linked Lists

With 2020 we are going to look at a new aspect of programming: data structures. It is often the case that everyone uses structures provided by the various programming languages.…

A Java approach: variables - use case

Hello all friends and welcome back! After the introduction made on the variables, we try to analyse some critical issues that may arise in quite common situations. Let's start by analysing…

Introduction to REGEX - Regular Expression

Today we are going to write about Regular Expressions known as regex or shortened  regexp, a very useful concept of using search patterns. Surely you were in a situation when you…

A Java approach: variables

Hello everyone and welcome back! Today we will begin a journey that will lead us to study, and possibly review, what are the basics of programming. We will start by talking…

HTTP Cookies: how they work and how to use them

Today we are going to write about the way to store data in a browser, why websites use cookies and how they work in detail. Continue reading to find out how…

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