JavaScript: Spread and Rest operators

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

by 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 Date: 05-04-2021 javascript programming code webdev hits : 11272  
 
 
 
 

Related Posts

How to upload files to the server using JavaScript

In this tutorial we are going to see how you can upload files to a server using Node.js using JavaScript, which is very common. For example, you might want to…

How to combine multiple objects in JavaScript

In JavaScript you can merge multiple objects in a variety of ways. The most commonly used methods are the spread operator ... and the Object.assign() function.   How to copy objects with…

The Payment Request API: Revolutionizing Online Payments (Part 2)

In the first part of this series, we explored the fundamentals of the Payment Request API and how it simplifies the payment experience. Now, let's delve deeper into advanced features…

The Payment Request API: Revolutionizing Online Payments (Part 1)

The Payment Request API has emerged as the new standard for online payments, transforming the way transactions are conducted on the internet. In this two-part series, we will delve into…

Android Hidden Codes: unveiling custom dialer codes and their functionality

In the world of Android smartphones, there exist numerous hidden codes that can unlock a treasure trove of functionalities and features. These codes, known as custom dialer codes, provide access…

Let's create a Color Picker from scratch with HTML5 Canvas, Javascript and CSS3

HTML5 Canvas is a technology that allows developers to generate real-time graphics and animations using JavaScript. It provides a blank canvas on which graphical elements, such as lines, shapes, images…

How do you stop JavaScript execution for a while: sleep()

A sleep()function is a function that allows you to stop the execution of code for a certain amount of time. Using a function similar to this can be interesting for…

Mastering array sorting in JavaScript: a guide to the sort() function

In this article, I will explain the usage and potential of the sort() function in JavaScript.   What does the sort() function do?   The sort() function allows you to sort the elements of…

Infinite scrolling with native JavaScript using the Fetch API

I have long wanted to talk about how infinite scroll functionality can be implemented in a list of items that might be on any Web page. Infinite scroll is a technique…

Sorting elements with SortableJS and storing them in localStorage

SortableJS is a JavaScript extension that you will be able to use in your developments to offer your users the possibility to drag and drop elements in order to change…

What is a JWT token and how does it work?

JWT tokens are a standard used to create application access tokens, enabling user authentication in web applications. Specifically, it follows the RFC 7519 standard. What is a JWT token A JWT token…

Template Literals in JavaScript

Template literals, also known as template literals, appeared in JavaScript in its ES6 version, providing a new method of declaring strings using inverted quotes, offering several new and improved possibilities. About…

Clicky