Rest and Spread in JavaScript

I wanted to talk a little bit today about the Rest Parameter and Spread Operator in JavaScript. When I first learned JavaScript, I knew where to use these these, but I didn’t really fully grasp the concepts behind them, so I thought it might be useful to you, to go through them a bit.

The rest parameter is shown by ... (three periods) and according to MDN, “The rest parameter syntax allows a function to accept an indefinite number of arguments as an array…”. In other words, it gives us a way to give a function any number of arguments that we want, without having to tell the function exactly how many arguments that is, and it converts those arguments into an array. Let’s look at an example…

function allTheArgs(...args) {
return args[2];
}
allTheArgs(5,6,7,8); // Returns 7allTheArgs("banana", "apple", "orange", "grape", "pineapple");
// Returns "orange"
allTheArgs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
// Returns 3

Here we created a simple function that takes a undefined number of arguments, by using the rest parameter, and just extracts the argument with the index of 2, in the array created by the rest parameter. As you can see, we can give allTheArgs() any number of arguments that we want and we can use different datatypes. So how does this help us? Well what if we wanted to know the sum of a bunch of numbers, but we don’t know how many numbers we’ll have…

function sumAllTheNumbers(...args) {
let sum = 0;
let i = 0;
while (i < args.length) {
sum += args[i];
i++;
}
return sum;
}
sumAllTheNumbers(1, 2); // Returns 3sumAllTheNumbers(10, 3, 15, 20, 60); // Returns 108sumAllTheNumbers(10); // Returns 10

So there you go, we have a function that will provide the sum of any number of arguments that we want to give it. Pretty cool, right?

One thing about the rest parameter, if you’re going to use it with other parameters in a function, the rest parameter needs to come last…

function thisWillNotWork(a, ...args, b) {
// some code
}
// This will not work because the rest parameter should be last
function thisIsFine(a, b, ...args) {
// some code
}
// This is the correct way to use the rest parameter with other parameters

The spread operator is shown the exact same way as the rest parameter with ... (three periods) and MDN says the spread operator, “allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected”. Ok, so to break this down, the spread operator is used on arrays or object literals, to well, spread them out into their elements or key-value pairs. We most commonly use the spread operator in function calls (where more than one argument is expected), to copy or clone, to concat, and to expand. Say we want to find the minimum value in a list of number…

console.log(Math.min(1, 2, 3, -1)); // Outputs -1 of course
// What if we tried an array?
let array = [1, 2, 3, -1];
console.log(Math.min(array));
// Returns NaN because Math.min won't work on an array

// Ok let's use the spread operator
console.log(Math.min(...array));
// Outputs -1 because the spread operator spreads the array into (1, 2, 3, -1) which Math.min can work with!

Here, the spread operator let’s us work on an array almost like it is a list. We can also use it to spread an array to use in a function call…

function addNumbers(num1, num2, num3) {
return num1 + num2 + num3;
}
let numbersArray = [3, 4, 5];addNumbers(...numbersArray); // Returns 12

What if we wanted to concat two arrays…

let arr1 = [1, 2];let arr2 = [3, 4];console.log(arr1.concat(arr2)); 
// Outputs [1, 2, 3, 4], this is normally how to concat
let newArr = [...arr1, ...arr2];
console.log(newArr);
// Outputs [1, 2, 3, 4] still but we used the spread operator!

What if we wanted to copy an array, but not change the original array…

let arr1 = [1, 2];let arr2 = arr1;arr2.push(3);console.log(arr2); // Outputs [1, 2, 3]console.log(arr1); // Outputs [1, 2, 3] OOPS! Not what we wanted!
// Enter the spread operator!
let arr1 = [1, 2];let arr2 = [...arr1];arr2.push(3);console.log(arr2); // Outputs [1, 2, 3]console.log(arr1); // Outputs [1, 2] there we go!

What if we wanted to combine the elements of two arrays…

let arr1 = [1, 2];let arr2 = [arr1, 3, 4];console.log(arr2); 
// Outputs [[1, 2], 3, 4], not quite what I wanted
// Using spread operatorlet arr1 = [1, 2];let arr2 = [...arr1, 3, 4];console.log(arr2);
// Outputs [1, 2, 3, 4] that's more like it!

Finally, objects…

let obj1 = {x: "Hello", y: "Hi"};
let clonedObj = {...obj1}; // Creates and spreads a copy of obj1
let obj2 = {a: "Goodbye", b: "Bye"};let mergedObjects = {...obj1, ...obj2};console.log(mergedObjects);
// Outputs {x: "Hello", y: "Hi", a: "Goodbye", b: "Bye"}

The rest parameter is used only in function declarations and is going to to take a number of function arguments and turns them into an array.

The spread operator is used in function calls and anywhere where you want to want to spread an array or object to manipulate it.

Well, there you go a break down of the rest parameter and the spread operator, I hope that you found this useful and thanks for reading!

Computer Support Tech turned Software Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store