JavaScript Rest Parameters

Before we see what the rest parameter is, let’s see another interesting thing about javascript functions and that is arguments. Each javascript function except the arrow function has an implicit object named “arguments” which as the name suggests, contains the value of all arguments passed to the function. And it means we can pass any number of arguments to a function taking advantage of arguments. Let’s see an example; the following function returns the sum of arguments passed to it and since it uses arguments it can calculate the sum of any number of arguments.

function addNumbers(){
    let sum=0;
    for(let i=0;i<arguments.length;i++){
        sum+=arguments[i];
    }
    return sum;
}
console.log(addNumbers()) //logs 0;

console.log(addNumbers(1,2)) //logs 3;

console.log(addNumbers(1,2,3,4,5)) //logs 15;

In the above code snippet, the addNumbers function iterates over the arguments object (yes, arguments is an object and not an array!) and calculates their sum. And from the 3 function calls we can see that the function can be called with 0, 2 or 5 arguments. It can be called using any number of arguments. This is similar to the params in C#.

The Rest Parameter is a functionality introduced in ES6 which also allows us to pass any number of arguments to a function just like arguments. However the arguments is an implicit object but the rest parameter needs to be defined as a function parameter. A parameter is made a rest parameter by prefixing the parameter with triple dots (…). The above addNumbers function can be defined using the rest parameter as shown below. It will still be called the same way as the above function.

function addNumbers(…numbers){
    let sum=0;
    console.log(typeof numbers);
    for(let i=0;i<arguments.length;i++){
        sum+=arguments[i];
    }
    return sum; 
} 
console.log(addNumbers()) //logs 0;
console.log(addNumbers(1,2)) //logs 3;
console.log(addNumbers(1,2,3,4,5)) //logs 15;
Even though the arguments and the rest parameters serve the same purpose, the rest parameter has some added advantages over arguments.

Advantage of JavaScript Rest Parameter

The first advantage is that the rest parameter can be used with arrow functions as well. And the second advantage is availability of array functions for the rest parameter. Since the arguments is an object,the array function like slice, splice, join, map etc cannot be used with the arguments even though it behaves like an array but those functions can be used with the rest parameter since it is an array. We can verify it using the following code snippet.

function addNumbers(){
    console.log(Array.isArray(arguments));
}
function addNumbersRest(...numbers) {
    console.log(Array.isArray(numbers));
}
addNumbers();  //logs false

So we can make the addNumbers function concise taking the advantage of one of the array functions “reduce”
// Regular function

function addNumbers(...numbers){

    return numbers.length==0 ?0 : numbers.reduce((num,sum)=>sum+num);

}
// Arrow function

let addNumbers=(...numbers)=>numbers.length==0 ?0 : numbers.reduce((num,sum)=>sum+num);

Use with ordinary parameter

Another difference between the arguments and the JavaScript Rest Parameter is their behaviour with ordinary parameters. When a function is defined with ordinary parameters then the arguments will contain the value of ordinary parameters along with all other arguments passed to the function. Whereas if a function is defined with ordinary parameters and rest parameter then the rest parameter will not contain the value of the ordinary parameters, it will contain the value of the rest of the arguments after the ordinary arguments and hence the name is the rest parameter. Let’s see an example.

function addNumbers(a,b){

    //To use the array functions with the arguments object, we can convert it to an array

    let numbers=Array.from(arguments);

    console.log(numbers.join(','));
}
function addNumbersRest(a,b,...numbers){

    console.log(numbers.join(','));
}
addNumbers(1,2,3,4,5);  //logs 1,2,3,4,5
addNumbersRest(1,2,3,4,5);  //logs 3,4,5

This behaviour can be helpful in the case when the ordinary parameter needs to be treated in a different way then other parameters. Let’s say we need to define a function that returns different power values of a number. We can use the mix of ordinary parameter and the rest parameter as shown in the below example.

function calculatePower(num,...powers){

    return powers.map(pow=>Math.pow(num,pow));

}
console.log(calculatePower(2,1,2,3,4,5)); //logs [2, 4, 8, 16, 32]

Mr. Dhaval Desai