//

ES6 DEFAULT, REST & SPREAD

Many programming languages support the concept of a default argument for a function parameter so that the caller does not always need to specify the argument value. Unfortunately, ES5 does not have a default argument support in its syntax. ES6 functions have come a long way by taking aboard the years of complaints and improving parameter handling that is less error-prone and more powerful.

default

Functions in JavaScript allow any number of parameters to be passed regardless of the number of declared parameters in the function definition. JavaScript programmers employ various different run-time tricks to achieve the effect of an argument with a default value. The common pattern for parameter handling is as follows:

function sum(number1, number2) {
    // set default to 0 if number2 not passed
    // (or passed as undefined)
    number2 = number2 || 0;
    return number1 + increment;
}

console.log(sum(2, 3)); // 5
console.log(sum(2));    // 2

The logical OR operator (||) always returns the second operand when the first is falsy.

ES6 gives us a way to set default function parameters. Any parameters with a default value are considered to be optional.

function inc(number1, number2 = 0) {
  return number1 + number2;
}

console.log(inc(2, 3)); // 5
console.log(inc(2));    // 2

You can also set default values to parameters that appear before arguments without default values:

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

console.log(sum(1, 5, 10));         // 16 -> b === 5
console.log(sum(1, undefined, 10)); // 13 -> b as default

You can even execute a function to set default parameter. So it’s not restricted to primitive values.

function getDefaultIncrement() {
  return 1;
}

function inc(number, increment = getDefaultIncrement()) {
  return number + increment;
}

console.log(inc(2, 2)); // 4
console.log(inc(2));    // 3

rest

In ES5, when you want to handle all the arguments passed into it, we would have to use the arguments object.

  function sum() {
   var numbers = Array.prototype.slice.call(arguments),
       result = 0;
   numbers.forEach(function (number) {
       result += number;
   });
   return result;
  }
  console.log(sum(1));             // 1
  console.log(sum(1, 2, 3, 4, 5)); // 15

Here we have to iterate the arguments array and sum up the numbers.

arguments object

The arguments object is not quite an array - it's an array like object. We have to convert it to an Array using the slice function.

ES6 introduces rest parameters to overcomes these difficulties.

Indicated by three dots ... similar to the splat operator in Ruby.

Named parameters become an array containing the rest of the parameters.

function sum(…numbers) {
  var result = 0;
  numbers.forEach(function (number) {
    result += number;
  });
 return result;
}

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

No other named arguments can follow in the function declaration.

The folowing will throw an error:

function sum(…numbers, last) { // causes a syntax error

spread

The spread is closely related to rest parameters, because of … (three dots) notation. It allows to split an array to single arguments which are passed to the function as separate arguments.

Let’s define our sum function and pass spread to it:

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

var args = [1, 2, 3];
console.log(sum(…args)); // 6

So instead using an apply function, we can just type …args and pass all array argument separately.

We can also mix standard arguments with spread operator:

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

var args = [1, 2];
console.log(sum(…args, 3)); // 6