Be careful when using || to set default values in JavaScript

(This post was originally titled "Don't use || to set default values in JavaScript". However, if you're careful to avoid the pitfalls and your whole team understands the syntax || can be convenient to use.)

If you’re working with JavaScript I’m sure you’ve seen code that uses the OR operator (||) like this:

function eatFruit (fruit) {
    fruit = fruit || "strawberry";
    ...
}

What does this do? It sets a default value!

When the function is called without any arguments the value of fruit is set to "strawberry".

If the fruit parameter is set it’s just assigned its own value, so the value doesn’t change.

This image shows the value of the fruit variable in each of the two scenarios:

Code paths for no parameter passed in and for passing in the string

This works because the OR operator isn’t restricted to combining Boolean values. All it does is return the first value if it’s truthy and the second value if the first value is falsy.

Should I use the OR operator to set default values?

Using OR for defaults can be convenient because it is short and easy to write. However, I don’t use it can also lead to unexpected bugs.

First of all, it isn’t obvious why the OR operator would be used to assign default values. It takes time for this hack to become intuitive.

More importantly, using || to set default values breaks down when falsy values, like 0 or “”, are passed into the function.

When no value is passed into a function the value of the parameter will be undefined. Using OR however means that the default value is used even when a valid falsy value is passed into the function.

Example: If the default value is 2 and you pass in 0 the function will use 2 instead of the value you passed in.

As a result OR adds mental overhead for whoever works on the function in the future. To avoid introducing bugs the developer must check whether there are any falsy values that might be passed to the function.

How to set defaults values instead

Instead of using || it’s better to use an explicit comparison with undefined:

function eatFruit (fruit) {
    if (fruit === undefined) {
        fruit = "strawberry";
    }
    ...
}

Yes, this is more verbose, but it’s also more resilient to new bugs.

If you’re using an options object default values can be set very cleanly with Underscore’s defaults function:

function eatFruit(options) {
    _.defaults(options, {fruit: "strawberry"})
}

Default parameters in EcmaScript 2015

The next version of JavaScript will include native support for default parameters, so above code can be rewritten much more cleanly:

function eatFruit (fruit = "strawberry") {
    ...
}

Unfortunately it will take a while until browsers support it.