I just launched a new course on ES6! Use the code WESBOS for $10 off.

Strengthen your core JavaScript skills and master all that ES6 has to offer. Start Now →

JavaScript Default Function Arguments

Default function arguments in JavaScript are here. This is one of those features that’s going to make your life much easier, and make your code much more readable and maintainable.

Let’s say we have a function called calculateBill which is going to take in three things: the total cost of your meal, how much tax we need to pay, and then how much you would like to tip your waiter:

function calculateBill(total, tax, tip) {
    return total + (total * tax) + (total * tip);
}

From that, we can return the total amount of hte bill.

Then we’ll make a new variable called totalBill, and we’ll use our new function, to figure out how much all of that costs.

function calculateBill(total, tax, tip) {
    return total + (total * tax) + (total * tip);
}

const totalBill = calculateBill(100, 0.13, 0.15);
console.log(totalBill);

On a $100 meal, with 13% tax and a 15% tip, the console will tells us 128, or $128.

What happens if we want to automatically assume 13% tax rate, and we want to assume a 15% tip rate?

What we could do is just pass in our $100 meal and get our result. If we omit tax and tipcalculateBill(100) our function returns us NaN, or “not a number”. That’s because we’re trying to do math against things that aren’t passed in.

function calculateBill(total, tax, tip) {
    console.log(tax);
    return total + (total * tax) + (total * tip);
}

const totalBill = calculateBill(100);
console.log(totalBill);

If you use console.log to show the value of tax or tip, you’ll see that they show up as undefined.

What we would normally do is we would add an if loop:

function calculateBill(total, tax, tip) {
    if(tax === undefined) {
        tax = 0.13;
    }
    if(tip === undefined) {
        tip = 0.15;
        }
    return total + (total * tax) + (total * tip);
}

const totalBill = calculateBill(100);
console.log(totalBill);

It works fine there, but there’s a whole lot of code that we added.

You might be saying, “Yeah, you can do this, tax equals tax,” or you can do this little trick here where you can say it equals itself.

function calculateBill(total, tax, tip) {
    tax = tax || 0.13;
    tip = tip || 0.15;
    return total + (total * tax) + (total * tip);
}

const totalBill = calculateBill(100);
console.log(totalBill);

I don’t mind that, but it can be a little bit hard on your team to have to read it. If you’ve got four or five different arguments coming in, then you’ve got to do all this crazy code at the top.

Another thing to note is the || trick will fallback to the default if you pass in 0, null, false or any other falsy value. Not exactly what you want when you are trying to tip $0!

So let’s just do without that entirely. What we can do now in ES6 is just simply set it when we define our function, and those things will be assumed.

function calculateBill(total, tax = 0.13, tip = 0.15) {      
    return total + (total * tax) + (total * tip);
}

const totalBill = calculateBill(100);
console.log(totalBill);

If nothing is passed in for that one, then the defaults are going to go ahead. There we’re good to go.

What else we can do?

What if I wanted to pass only the total amount, as well as the tip amount, because I’m a big tipper. Let’s say I’m tipping 25% here, and the tax rate isn’t going to change because I’m still in Ontario.

However, if I just leave the tax empty, we’ll get a syntax error, like I would here:

function calculateBill(total, tax = 0.13, tip = 0.15) {      
    return total + (total * tax) + (total * tip);
}

const totalBill = calculateBill(100, , 0.25);
console.log(totalBill);

How do you leave a hole in here?

Well, what does this essentially check for? It checks for tax being passed undefined so you can just explicitly pass undefined:

function calculateBill(total, tax = 0.13, tip = 0.15) {      
    return total + (total * tax) + (total * tip);
}

const totalBill = calculateBill(100, undefined, 0.25);
console.log(totalBill);

The function is going to say, “Oh, no one passed any tax.” our default 13% and then the big tip is going to kick in here, and we get 138, or $138.

I’ve got another example similar to this one where this is order dependent, and when we hit destructuring, I’m going to show you how do you use an object in destructuring, so that you could pass this in any order, as well as have default arguments. But more on that later.

This entry was posted in ES6, JavaScript. Bookmark the permalink.

3 Responses to JavaScript Default Function Arguments

  1. MaxArt says:

    Pro-tip: instead of using undefined, you can always use `void 0`, which is shorter, or even better:

    let _;
    const totalBill = calculateBill(100, _, 0.25);

    Of course, if _ has already been taken by Lodash/Ramda/whatever, you can stick to whatever you like.
    The underscore is just more expressive as a placeholder.

    • wesbos says:

      Not sure I like void 0 or having to declare an undefined variable before using it – it’s not immediately as clear as using undefined. But to each their own – others may enjoy this way 🙂

    • HelpfulHand says:

      Nice Pro-tip MaxArt! Although using an “undefined” without declaration represents the primitive undefined, it can be hijacked in the global scope and then cause inconsistencies in the API for calculateBill.

      Passing in an “undefined” parameter, be it declared or not, in order to trigger a default state of a call signature for the calculateBill routine seems a bit of a kluge.

      Although ES6 provides this functionality, I would say placing multiple default values next to each other in the parameters should be reconsidered.

      By swapping tax and tip and not providing tip with default parameter, as follows:

      function calculateBill( total, tip, tax = 0.13){ … }

      you simple have to omit passing in the variable all together.

      calculateBill( 100, 0.15 );
      //Here tax will be set to the default value

      What would be better yet would be to pass in a single object of all the optional components, and actually write all the “extra” code to do the default checking for you.

      function calculateBill( total, optionalArgs ){
      var tax = optionalArgs.hasOwnProperty(“tax”) ? optionalArgs.tax : 0.13;
      var tip = optionalArgs.hasOwnProperty(“tip”) ? optionalArgs.tip : 0.15;
      return total + (total * tax) + (total * tip);
      }

      var total = 100;
      var optArgs = {};

      optArgs.tip = 0.15;
      optArgs.tax = 0.13;

      var totalBill = calculateBill( total, optArgs );

      Keep in mind that you could also just pass in a single option argument with all three parameters in them.

      JS 101 will tell you this is not good to pass around undeclared variables into a function. Please refrain from encouraging bad practice for people getting into JavaScript, especially with all the fancy new features newer versions are providing.

Leave a Reply

Your email address will not be published. Required fields are marked *