Alright, this is something I've seen too many times in JavaScript code—even professionally—so I am going to address it here. This mistake is an easy one to make, and I use to make this mistake all the time; it's easy, simple, tempting, and nigh impossible to debug. I present to you: the null-coalescing operator. That is, the simple double-bar
||
. Now, you might be wondering, "what's so bad about it?" Well, nothing. It's just bad programmers using it incorrectly.
The
||
operator is used in JavaScript not only to describe a disjunction, but also to specify default parameters to a function. (It's used in place of default parameter assignment, i.e. the one in
function foo(bar=5){}
, setting
bar
to 5.) It might be used (correctly) in the following situation:
function add(x, y, z){
z = z || 0;
return x + y + z;
}
This function successfully does what it's supposed to: add
x
and
y
, and
z
if specified. This works because of the short-circuiting property of
||
. This operator is roughly equivalent to the following function:
function disjunction(LHS, RHS){
if(LHS){
return LHS;
} else {
return RHS;
}
}
In this case, when the
LHS
is undefined, the value of the expression is
RHS
. However, the obverse of the statement (i.e. when
LHS
is defined then the value is not
RHS
and is thus is
LHS
) does not hold. Observe:
function multiply(x, y, z){
z = z || 1;
return x * y * z;
}
This works for most testcases (try it yourself) except for when
z === 0
; the expected result is
0
, but what we get is
x * y
. Why? Well, let's look at what the disjunction yields.
z = z || 1
becomes
z = 0 || 1
, which becomes
z = 1
, the incorrect result. This is why I follow this rule:
when the RHS to the disjunction is truthy, use typeof z === "undefined" ? default : z
; otherwise, one can use ||
.