Javascript false expressions evaluating to true
The truthy may hurt for a little while, but a falsy hurts forever
Good day, fellow reader.
As a programmer, I sometimes need to jump between languages, and changing not only involves a different syntax but also setting up your mind to the tricky or handy ways things are done in every one of them.
The bug 🐞
I switched to Javascript, and I was debugging something (a Node.js API). It seemed that some part of a really long task was not working properly. Then, just before going into debug mode, I saw it. I mean, for a JS-only developer this might be an easy spot.
The simplified version of the code was:
res = await fetchDataFromDatabase(transaction);
if (res) {
responseObject.response = res;
// more stuff
}
// Continue from here if res is empty?
So, when res
was []
(semantically an empty response), the if was evaluated to true
, and the "more stuff" part was done. That is pretty different from other languages, and I will just demonstrate a few.
PHP
if ([]) {
echo "won't get here";
} else {
echo "empty arrays evaluate to false";
}
// Output: empty arrays evaluate to false
Python
res = []
if res:
print ("never got here")
else:
print ("empty arrays evaluate to false")
# Output: empty arrays evaluate to false
Java
The thing gets interesting here:
String[] res;
if(res) {
System.out.println("ENTERED");
}
Will throw a nice incompatible types: String[] cannot be converted to boolean
C / C++
Oh, that won't even be a problem because why would you want an empty array in C.
The reason 🤙
Of course, there was an explanation for that behavior. But let me say that if you go to the console and do:
[] == false
// output is true
But if you continue in the console and try this:
if ([]) {
"yes"
} else {
"no"
}
// output is yes
I know Biff, wasn't []
type coerced to false?
Under the hood, things happen. Consider these statements.
if (Expression) {}
while (Expression) {}
According to ECMAScript 2021 Language Specification, after an expression is evaluated, a ToBoolean function is called for that value.
That function ToBoolean(argument)
will return argument
if it is of type Boolean (true
or false
) otherwise, it is going to cast it according to the following table:
argument | ToBoolean(argument) |
false | false |
0 | false |
-0 | false |
0n | false |
"", '', `` | false |
null | false |
undefined | false |
NaN | false |
document.all | false |
everything else | true |
The first 9 rows are known as Falsy values.
Everything else is returned as
true
in the ToBoolean function. Those values are known as Truthy values
What's important here ❗
So, remembering the falsies, we can be certain that every other value/object will be evaluated as true
. And that includes our beloved []
See you around!