Setting default values in JavaScript with the OR operator

2 minutes read

JavaScript is not a perfect language; it’s missing some important features of modern languages, such as default values for parameters (an issue that’s fixed in ES6). There’s a pattern in wide use that provides something similar to default parameters, and it looks something like this:

function User(name, age) {
    this.name = name || "Leonard Finch";
    this.age = age || 18;
}

This takes advantage of JavaScript’s dynamic typing and loose definition of true (or ‘truthy values’) and false (or ‘falsy values’). In short, the actual boolean value false, and empty string, the number zero, and the types undefined and null are falsy. Everything else is truthy (yes, including empty arrays and objects, see the test below). This code first checks the parameter’s value, which is converted to a boolean because of the boolean OR operator, and will set this.name to name if it’s a truthy value. The right side of the OR operator will be short-circuited, that is, it will not be executed because the left hand side is true, which means the result of the statement will be true regardless of what the value on the left side is. There’s nothing to be gained by executing it, so the compiler just ignores it.

That’s a handy little trick, isn’t it? It’s not as compact as providing for the ability to set a default parameter right in the parameter list, but it’s only a single line per parameter. There’s absolutely nothing els that could possibly go wrong with this approach, is there?

Well, yes, there is. What if age is zero? Zero is a valid age, yet if it’s provided here, this.age will be reset to 27 because the numeric value 0 is ‘falsy’, and will trigger the right hand side of the logical or (||).

The same would apply to a name that consisted of an empty string. Think of a web form, and the user doesn’t enter a name. This User function will receive an empty string (falsy) as the name, and then apply the default value, something the user might not have expected.

A better way to handle defaults (aside from starting to use ES6) is to do null checks instead:

this.age = (age != null) ? age : 27

You can keep it on one line by using a ternary operator, and it’s really a better self-documenting expression. Also, non-strict equality is used because we don’t need to differentiate between null and undefined. If we had to use strict equality, we’d need to check against both null and undefined: ((age !== null) || (age !== undefined))

For good measure, here’s the test showing truthy and falsy values mentioned earlier.

See the Pen jrPorP by Jack Littleton (@jacklittleton) on CodePen.