In this article of the ES2015 features, we are going to discuss the default parameters/arguments values, spread operators, and rest parameters.

Default Arguments'/Parameters' Values

This feature exists in various programming languages. However, just until ES6, JavaScript didn't have this feature.

Before ES2015, we would imitate the behavior of default parameters' values as shown in the following example.

function sum(a, b){
    if (typeof(a) === 'undefined') a = 0;
    if (typeof(b) === 'undefined') b = 0;

    return a + b;
}

sum(); // 0
sum(1); // 1
sum(1, 2); //3 

This is verbose and tends to be misleading in some cases. Some would even define a utility function (most likely named default), and wrap that check in it instead of having such dangling if statements at the top of the function.

Nevertheless, this is solved when ES2015 introduced this feature. Let's explore by modifying the previous example.

function sum(a = 0, b = 0){
    return a + b;
}

sum(); // 0
sum(1); // 1
sum(1, 2); //3

We used destructuring assignment in the previous article to achieve this same functionality. However, this is more efficient and less verbose.

Spread Operator

Spread syntax allows an iterable such as an array expression 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. - MDN

Simply placed, the spread operator is utilized for array's or iterable object's construction and destructuring for using to populate function's arguments from an array on invocation.

Usually, we would have to call functions with Function.prototype.apply when passing an array of arguments like so:

function doStuff (x, y, z) { }
var args = [0, 1, 2];

// Call the function, passing args
doStuff.apply(null, args);

Now with the spread operator, we can do call the function like so:

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);

No need for the apply() or the null.

Spread operator is also used for combining arrays. There are plenty of ways to combine arrays such as using concat() or using a loop with Array.prototype.push. However, I find the spread operator to be the friendliest and the most useful. For instance, it would take a bit amount of work to achieve the following.

var arr1 = [2, 3];
var arr2 = [1, ...arr1, 4, 5];

console.log(arr2); //[1, 2, 3, 4, 5]

Rest Parameters

The rest parameter syntax is close to the spread operator syntax. It allows us to represent an indefinite number of arguments as an array. If you are familiar with Python, you will find the idea similar to the argument list *args. The syntax looks like the following.

function f(a, b, ...theArgs) {
    // ...
}

If the last named argument of a function is prefixed with ..., it becomes an array whose elements from 0 (inclusive) to theArgs.length (exclusive) are supplied by the actual arguments passed to the function.
In the above example, theArgs would collect the third argument of the function (because the first one is mapped to a, and the second to b) and all the consecutive arguments. - MDN

Let's take an example.

function sum(...numbers) {
    return numbers.reduce(function (sum, next) {
        return sum + next;
    });
}

console.log(sum(5, 10, 25)); //40

But wait a minute, JavaScript has arguments as parameters in ES5, why would I use rest parameters? Well, to begin with, arguments is not actually and array, but rather an array-like object, which means that the Array functions won't work on it. Therefore, the previous example won't work because we used the reduce(..) function.

It is worth to mention that the rest operator must be the last parameter to a function.

function f(a, ...b, c) {}
// SyntaxError: Rest parameter must be last formal parameter