Using Default Parameters and the Rest Operator in JavaScript
Tags: javascript, webdev, beginners, tutorial
Published: 2020-01-09 03:20:18

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

With the 2015 version of JavaScript, JavaScript functions can now accept default parameters in functions and there’s the rest operator to capture optional arguments in an array.

This is handy for handling optional parameters and there are many use cases for these features. Before we had these two features, all we had was the `arguments` object with the list of arguments of the function that was called.

All we could do to prevent undefined errors for optional parameters was to check each argument directly to see if they were defined and then set the value directly.

This is painful for developers as it’s possible to have a long list of optional arguments that we want the function to get. With default parameters, the default value for parameters is set directly in the signature of the function. This eliminates many lines of code that check the code.

* * *

Default Parameters
==================

Default parameters are easy with JavaScript. To set them in our code, we write the following:

```javascript
const sum = (a,b=1) => a+b
```

In the code above, we set the default parameter value of `b` to `1`, so if the second argument isn’t passed in when we call the `sum` function, then `b` is automatically set to `1`.

So, if we call `sum` as follows, we get `2` returned:

```javascript
sum(1)
```

As we can see, now we don’t have to worry about having optional arguments being `undefined`, which would be the alternative result if no default value is set for parameters. This eliminates many sources of errors that occur when making parameters optional with JavaScript.

The alternative way, without using default parameters, would be to check if each parameter is `undefined`. We write the following to do this:

```javascript
const sum = (a,b,c)=>{  
  if (typeof b === 'undefined'){  
    b = 1;  
  } 
  if (typeof c === 'undefined'){  
    c = 1;  
  }  
  return a+b+c;  
}
```

If we call the following `sum` function without parameters, we get:

```javascript
const sum = (a,b = 1,c = 1)=> a+b+c;  
sum(1) // returns 3  
sum(1, 2) // returns 4
```

As we can see, we handled missing parameters gracefully with default parameters.

For default parameters, passing in `undefined` is the same as skipping the parameters. For example, if we call the following function and pass in `undefined`, we get:

```javascript
const sum = (a,b = 1,c = 1)=> a+b+c;  
sum(1,undefined) // returns 3  
sum(1,undefined,undefined) // returns 3  
sum(1, 2,undefined) // returns 4
```

Note that `undefined` is the same as skipping parameters.

This isn’t true for other falsy values that are passed into a function. So, if we pass in `0`, `null`, `false`, or empty string, they get passed in and the default parameter values will be overwritten.

For example, if we have the code below:

```javascript
const test = (num=1) => typeof num;  
test(undefined);  
test(null);  
test('');  
test(0);  
test(false);
```

We get `number` for `test(undefined)`, `object` for `test(null)`, `string` for `test(string)`, `number` for `test(0)`, and `boolean` for `test(false)`.

This means that anything other than `undefined` is passed in, but note that if we pass in falsy values and then run arithmetic operations on them, falsy values get converted to `0`.

```javascript
const sum = (a,b = 1,c = 1)=> a+b+c;  
sum(1,null)  
sum(1,null,false)  
sum(1, 2,'')
```

So, `sum(1, null)` returns `2` as `b` is converted to `0` and `c` has the default value of `1`.

`sum(1)` returns `1` as `b` and `c` are converted to `0`. `sum(1, 2,’’)` is `3` as `a` is `1`, `b` is passed in so that it becomes `2` instead of getting the default value of `1`, and `c` is an empty string which is converted to `0`.

Default arguments are evaluated at call time, so that they’re set each time they’re called if no argument is passed into the function parameter with default values.

For example, if we have:

```javascript
const append = (val, arr = [])=>{  
  arr.push(val);  
  return arr;  
}  
  
append(1);  
append(2);
```

`append(1)` returns `[1]` and `append(2)` returns `[2]` as we didn’t pass in an array to each function call, so `arr` is set to an empty array each time it’s run.

It’s also important to know that we can pass in values returned by functions in the default parameter, so if we have a function that returns something, we can call it in the default parameter and assign the returned value to the parameter.

For example, we can write:

```javascript
const fn = () => 2  
const sum(a, b = fn()) => a+b;
```

Then, if we call `sum(1)`, we get `3` as the `fn` function returns `2`. This is very handy if we want to manipulate and combine values beforehand, before assigning it as a parameter.

Another great feature of the default parameters is that the parameters left of the given parameter are available for the parameter for assignment as default values, so we can have a function like the function below:

```javascript
const saySomething = (name, somethingToSay, message = `Hi ${name}. ${somethingToSay}`) => ({  
  name,  
  somethingToSay,  
  message  
});
```

Notice that we assigned an expression to the `message` parameter in the `saySomething` function. This is great for manipulating data and then assigning as we did before by assigning the function.

We can also see that we can have default parameters that depend on parameters that are to the left of it. This means that default parameters do not have to be static.

So, we call it with the first two parameters filled in, like `saySomething(‘Jane’, ‘How are you doing?’)`. We get:

```javascript
{name: "Jane", somethingToSay: "How are you doing?", message: "Hi Jane. How are you doing?"}
```

The `message` is returned with the template string that we defined evaluated.

We cannot call functions nested inside a function to get the returned value as the default parameter value. For example, if we write:

```javascript
const fn = (a = innerFn())=>{  
  const innerFn = () => { return 'abc'; }  
}
```

This will result in a `ReferenceError` being thrown, because the inner function isn’t defined yet when the default parameter is defined.

We can also have default parameter values that are set to the left of required parameters. Arguments are still passed into parameters from the left to the right, so if we have:

```javascript
const sum = (a=1,b) => a+b
```

If we have `sum(1)`, we have `NaN` return `1`. It is added to `undefined` as we didn’t pas in anything for the second argument, so `b` is `undefined`.

However, if we write `sum(1,2)` then `3` is returned as we have `a` set to `1` and `b` set to `2`.

Finally, we can use a destructuring assignment to set default parameter values. For example, we can write:

```javascript
const sum = ([a,b] = [1,2], {c:c} = {c:3}) => a+b+c;
```

Then, we call `sum` without arguments. We get `6` because `a` is set to `1`, `b` is set to `2`, and `c` is set to `3` by the destructuring assignment feature that JavaScript provides.

* * *

Rest Operator
=============

The rest operator is a JavaScript operator where we can store an indefinite number of arguments in a function as an array.

It looks exactly like the spread operator, which lets us spread entries of an array or a list of key-value pairs of an object into another object.

For example, if we have a function that has a long list of arguments, we can use the rest operator to shorten the list of parameters in a function.

The rest operator is used with the following syntax:

```javascript
const fn = (a,b,..restOfTheArgs) => {...}
```

Where `restOfTheArgs` is an array with the list of arguments other than the first two. For example, if we want to write a `sum` function that takes an indefinite list of numbers as arguments and sum up the numbers, we can write:

```javascript
const sum = (a,b,...otherNums) => {  
  return a + b + otherNums.reduce((x,y)=>x+y, 0);  
}
```

As we can see, this is very handy for functions that have a list of arguments. Before we had this, we had to use the `arguments` object available in functions to get a list of arguments.

This is not ideal, as we allow them to pass in anything into the arguments. With the rest operator, we have the best of both worlds. We can have some fixed parameters, while the rest stays flexible.

This makes functions more flexible than functions with a fixed number of parameters, while having some flexibility with functions that take an indefinite number of arguments.

The `arguments` object has all the arguments of the function. Also, it’s not a real array, so array functions aren’t available to them. It’s just an object with indexes and keys to denote the argument’s positions.

Methods like `[sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)`, `[map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)`, `[forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)`, or `[pop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop)` cannot be run on the `arguments` object. It also has other properties. This creates confusion for programmers.

The arguments that are converted to an array with the rest operator do not have these issues, as it is a real array.

To call the `sum` function we wrote, we can write:

```javascript
const result = sum(1,2,3,4,5,6,7,8,9,10);
```

`result` will be `55`, as we summed up all the arguments together. `otherNums` is an array with all the numbers other than 1 and 2.

We can also use the rest operator to destructure a list of arguments into a list of variables. This means that we can convert a list of parameters into an array with the spread operator, and then decompose the array of arguments into a list of variables.

This is very useful because we can get the entries of the array that’s operated on by the rest operator and convert them to named variables.

For example, we can write:

```javascript
const sum = (a,b,...[c,d,e])=> a+b+c+d+e;
```

This way, we can use the rest operator but limit the number of arguments that your function accepts.

We take the function parameters `a` and `b`, and we also take `c`, `d`, and `e` as parameters. However, it’s probably clearer without using the rest operator as all the parameters are fixed, we can just list the parameters directly.

* * *

Conclusion
==========

Now that we have the 2015 version of JavaScript, we can do many handy things with parameters.

Default values and the rest operator are handy for handling missing or operation parameters. Default parameters let us set default values for parameters that might not have anything passed in function call arguments.

The rest operator lets us retrieve some or all items listed in the argument as an array. Letting us manipulate them with array operations or using the destructuring assignment to decompose them into individual variables.