The Complete Magazine on Open Source

JavaScript: The New Parts

SHARE
/ 185 0

This is the fifth part of our series on ECMAScript 2015. Read on to understand more about default parameters, rest parameters and spread operator.

JavaScript language is evolving more rapidly than in the past. New features are getting added every year. So let’s learn more about the latest features in order to make your programming easier, bug-free and maintainable.
One of the unique features of JavaScript is the support for functions in the language. Functions are first class citizens, which means you can do all the operations using functions that you can do with other primitive data types. ECMAScript 2015 introduces features that make functions more powerful and convenient. In this issue, we will learn about features related to function parameters, namely, default parameters, rest parameters and spread operators.

Default parameters
A function can have zero or more parameters. If a function has two parameters, it is expected that two values are passed when calling the function. If the number of parameters passed is less, the JavaScript interpreter assumes the value of the missing parameters as undefined. There is no exception thrown. This implicit assignment of undefined parameters can lead to issues. Thankfully, IDEs show function signatures for programmers, which helps to avoid parameters being missed. But as a good programming practice, it is required that you handle these scenarios as part of the function.

function fn(one, two, three) {
console.log(one, two, three);
}
fn(1);

Output: 
1, undefined, undefined

In ES6, we have a new feature called default parameters, which serves the purpose of giving a value to a parameter other than undefined. At the time of calling the function, it need not include a value for these parameters; these are optional. This also avoids conditional statements to check undefined, all through your function. This feature is there in other languages like Python, C++ and C#. It is also called default arguments (Wikipedia).
Shown below is a function for computing simple interest which takes the principal, time and rate of interest. Let’s assume that in every call the principal has a value, and the time and rate of interest are fixed at 1 and 8, respectively, when no value is passed.

1. function simple_interest(p, t, r) {
2. let time = t || 1;
3. let rate = r || 8;
4. let si = (p * time * rate)/100;
5. console.log(“p =” + p + “, t = “+ time + 
6. “, r = “+rate + “; si = “ + si);
7. }
8. simple_interest(1000, 2, 10);
9. simple_interest(1000, 5);
10. simple_interest(1000);
11. simple_interest(1000, 2, undefined);
12. simple_interest(1000, 2, null);
13. simple_interest(1000, 2, 0);

The output is::

p =1000, t = 2, r = 10; si = 200
p =1000, t = 5, r = 8; si = 400
p =1000, t = 1, r = 8; si = 80
p =1000, t = 2, r = 8; si = 160
p =1000, t = 2, r = 8; si = 160
p =1000, t = 2, r = 8; si = 160

Check this example at http://www.es6fiddle.net/ii88u9ol/
In the above example, in Lines 11, 12 and 13 we are passing undefined, null and 0. For all these three cases, Line 3 evaluates the OR condition and assigns the default rate of interest to 8.
Let us write the same function using default parameters as shown below. Along with function parameters, we are also giving default values to the time and rate of interest. Again, here the assumption is that at least the principal amount is passed at the time of calling.

1. function simple_interest(p, t=1, r=8) {
2. let si = (p * t * r)/100;
3. console.log(`p = ${p}, t = ${t}, 
4. r = ${r}; si = ${si}` );
5. }
6. simple_interest(1000, 2, 10);
7. simple_interest(1000, 5);
8. simple_interest(1000);
9. simple_interest(1000, 2, undefined);
10. simple_interest(1000, 2, null);

The output is:

p = 1000, t = 2, r = 10; si = 200
p = 1000, t = 5, r = 8; si = 400
p = 1000, t = 1, r = 8; si = 80
p = 1000, t = 2, r = 8; si = 160
p = 1000, t = 2, r = null; si = 0

With default parameters, not passing a parameter or passing an undefined one has the same result. But when ‘null’ is passed, the default value for the parameter is not applied. Remember that ‘null’ is a valid value. Play around with the above example at http://www.es6fiddle.net/ii851m5f/
In addition to assigning values, we can also pass expressions or functions. For example:

function simple_interest(p, t=1,
r=Math.floor(Math.random()*10))

The rate of interest is passed as a random number between 0 to 9.

Rest parameters
There are a set of features which were discussed and debated in earlier ECMAScript versions, but never standardised. These have been introduced as a part of ES6. One such feature is rest parameters.
In JavaScript, the arguments object is available in every function as a local variable. All parameters passed to a function are stored as arguments array in the variable. The use of this object is deprecated and discouraged. For backward compatibility, arguments will be still supported in JS engines. In ES6, there is a symbol for rest parameters (…) which helps many values to be passed to a function. A series of values is captured as an array with a name that can be specified in the function definition.

1. function add(...nums) {
2. var result = 0;
3. nums.forEach(function (num) {
4. result += num;
5. });
6. return result;
7. }
8. add(10, 20, 30, 50);

In Line 1, note the new operator, which is three dots. This denotes rest parameters. Note that nums is a rest parameter, which is an array. To add numbers, use the array method forEach to add each value.
Rest parameters can also be used along with fixed parameters followed by a variable number of parameters. To make the above function more generic, we can make the first argument of the function take the type of operation.

function math(operation, ...nums)

The first parameter could indicate any operation like addition, multiplication, maximum or minimum.
When using rest parameters, ensure that this parameter is the last argument in the function. If any other parameter follows the rest parameter, a syntax error is thrown. One of the major differences between the rest parameter and arguments is that the former is a pure array and it is iterable. This gives a huge advantage when operating on a set of values. This also gives flexibility of fixed parameters and a variable number of parameters.

Spread operator
Another feature related to rest parameters is the spread operator. The rest parameter is used to represent a list of values as one array variable. The spread operator is used to expand an array into individual values in the function call.

1. function max(a, b, c) {
2. // code to find max of three numbers
3. }
4. let a = [10, 20, 30];
5. max(...a); // = max(10, 20, 30)
6. let b = [...a, 40, 50];

In Line 5, the function max is called with array name using a spread operator. This is equivalent to passing three values individually. Similarly, in Line 6, variable a is used with the spread operator to denote the first three elements of array b. The spread operator is being used to concatenate arrays.

The ES6 support matrix

Untitled
In previous versions of JavaScript, there was a method .apply() for the same purpose. This method is part of Function.prototype. The apply method takes this as the first argument. The spread operator is simpler and more readable.
In the next issue, we will learn about destructuring. This feature makes extracting subsets of object attributes really simple. It reduces many lines of code to traverse objects and a select few properties.

References
[1] Play around with ES6 features online: http://www.es6fiddle.net/
[2] Kangax support matrix: http://kangax.github.io/compat-table/es6/