Javascript false expressions evaluating to true

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.

Ready doc from back to the future Doc from "Back to the future" (Movie)

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
What the hell is going on here - Biff - Back to the future 2 Biff from "Back to the future part II" (Movie)

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:

argumentToBoolean(argument)
falsefalse
0false
-0false
0nfalse
"", '', ``false
nullfalse
undefinedfalse
NaNfalse
document.allfalse
everything elsetrue

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!