Often times when writing a function, you need to assign default values for arguments that weren't passed to the function when it was invoked.
For example, let's say we were creating a calculatePayment
function. This function has three parameters, price
, salesTax
, and discount
. The purpose of this function, as the name implies, is to calculate the final price of a bill taking into account the initial price as well as any sales tax or discounts that should be applied.
With a function like this, the only parameter that we want to make required is the price
. We'll set the default value of salesTax
to 0.05
(5%) and the default value of discount
to 0
so our function will still work if those values aren't passed in when the function is invoked. This way, the consumer of this function can supply a sales tax as well as a discount if they want, but if they don't, the default values will kick in.
calculatePayment(10) // 9.50calculatePayment(10, 0, 10) // 9.00
Historically, one way you could accomplish this is by using the Logical ||
operator.
function calculatePayment (price, salesTax, discount) {salesTax = salesTax || 0.05discount = discount || 0// math}
If you're not familiar with ||
, you can think of it like you would an if
statement checking for falsy values.
function calculatePayment (price, salesTax, discount) {if (!salesTax) {salesTax = 0.05}if (!discount) {discount = 0}// math}
However, this approach has some downsides. Can you spot the issue? What if we wanted to set the salesTax
to 0
? With our current implementation that would be impossible since 0
is classified as a falsy value so our if (!salesTax)
would always evaluate to true
setting the salesTax
to our default value of 0.05
. To fix this, let's check for undefined
rather than falsy.
function calculatePayment (price, salesTax, discount) {salesTax = typeof salesTax === 'undefined' ? 0.05 : salesTaxdiscount = typeof discount === 'undefined' ? 0 : discount// math}
Now, both salesTax
and discount
will only take on their default values if their arguments are undefined
.
At this point our code works well, but as you'll see, there's now a better way to do this with ES6's "Default Parameters".
Default Parameters
Default Parameters allow you to set the default values for any parameters that are undefined
when a function is invoked. Using Default Parameters, we can now update our calculatePayment
function to look like this,
function calculatePayment (price, salesTax = 0.05, discount = 0) {// math}
Now, just as we had before, if salesTax
or discount
are undefined
when calculatePayment
is invoked, they'll be set to their default values of 0.05
and 0
.
Required Arguments
One neat trick you can do using Default Parameters is to throw an error if a function is invoked without a required argument. For example, what if we wanted calculatePayment
to throw an error if the price
wasn't specified when it was invoked?
To do this, first create the function that will throw the error.
function isRequired (name) {throw new Error(`${name} is required`)}
Next, using Default Parameters, assign the required parameter to the invocation of isRequired
function calculatePayment (price = isRequired('price'),salesTax = 0.05,discount = 0) {// math}
Now if calculatePayment
is invoked without a price
, JavaScript will invoke the isRequired
function, throwing the error. Clever? Totally. A good idea? I'll leave that up to you.