Rest Parameters and Spread Syntax
In this article, I want to talk about the famous three-dots in JavaScript. Depending on the context it is used, it either refers to Rest parameters or a spread syntax. Let's start with Rest parameters.
Rest Parameters
Passing (an) arguments to a function is a regular practice in any language. In strict languages like Java, the number of arguments that has been passed when a function is called should be exactly the same as the number of parameters set in the function signature. Otherwise the compiler will throw an error. In JavaScript, however, there is no such a limitation. You can pass any number of arguments to a function no matter how the function is defined input-wise.
function sum(a, b) { return a + b; }
alert(sum(1, 2, 3, 4, 5)); // returns 3
This code runs fine; however it only returns the sum of the first two arguments and the rest just waste the memory.
The issue with this having a set number of arguments in a function signature is the code inflexibility. What if we want to pass add three numbers instead of two? Should we write another function? What if we need to add four numbers?
Here comes the three-dots to the rescue! When using it in the function signature, three-dots can create an array to collect all the arguments passed to the function. Then using a for loop we can have access to all of them inside the function.
function sumAll(...args) { // args is the name for the array let sum = 0; for (let arg of args) sum += arg; return sum; } alert( sumAll(1) ); // 1 alert( sumAll(1, 2) ); // 3
alert( sumAll(1, 2, 3) ); // 6
We can even mix the rest parameters with individual parameters:
function showName(firstName, lastName, ...titles) { alert( firstName + ' ' + lastName ); // Julius Caesar // the rest go into titles array // i.e. titles = ["Consul", "Imperator"] alert( titles[0] ); // Consul alert( titles[1] ); // Imperator alert( titles.length ); // 2 }
showName("Julius", "Caesar", "Consul", "Imperator");
Please note that the rest parameters should always comes at the end; otherwise it throws an error.
function f(arg1, ...rest, arg2) { // arg2 after ...rest ?! // error
}
Spread Syntax
Above, we see how to get an array from the list of parameters. But sometimes we want to destruct an array or an object into a list of parameters so that we can work on them separately. For instance, the built-in function Math.max returns the greatest number in a list.
alert( Math.max(3, 5, 1) ); // 5
This function accepts only primitive types and won't work with an array of numbers.
let arr = [3, 5, 1]; alert( Math.max(arr) ); // NaN The solution is to use spread syntax as below: let arr = [3, 5, 1];
alert( Math.max(...arr) ); // 5 (spread turns array into a list of arguments)
By putting three-dots before the name of an array, the engine destruct it into a list of parameters. Unlike rest parameters, the spread syntax can be placed anywhere when it is used with individual parameters or multiple times:
let arr1 = [1, -2, 3, 4]; let arr2 = [8, 3, -8, 1]; alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25 Another usage for spread syntax is to merge arrays: let arr = [3, 5, 1]; let arr2 = [8, 9, 15]; let merged = [0, ...arr, 2, ...arr2];
alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2)
As mentioned before, the spread syntax can be used to destruct objects as well. One use case is making a copy of an object. The classic way of doing this operation is Object.assign(). It is possible to do the same thing with the spread syntax.
let obj = { a: 1, b: 2, c: 3 }; let objCopy = { ...obj }; // spread the object into a list of parameters // then return the result in a new object // do the objects have the same contents? alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // true // are the objects equal? alert(obj === objCopy); // false (not same reference) // modifying our initial object does not modify the copy: obj.d = 4; alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4}
alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}
This is so much shorter than using Object.assign() and makes our code much cleaner.
Source:
All the code examples are from: https://javascript.info/rest-parameters-spread