Why do empty JavaScript arrays evaluate to true in conditional structures?
JavascriptArraysObjectConditional StatementsJavascript Problem Overview
I was encountering a lot of bugs in my code because I expected this expression:
Boolean([]);
to evaluate to false.
But this wasn't the case as it evaluated to true.
Therefore, functions that possibly returned []
like this:
// Where myCollection possibly returned [ obj1, obj2, obj3] or []
if(myCollection)
{
// ...
}else
{
// ...
}
did not do expected things.
Am I mistaken in assuming that []
an empty array?
Also, Is this behavior consistent in all browsers? Or are there any gotchas there too? I observed this behavior in Goolgle Chrome by the way.
Javascript Solutions
Solution 1 - Javascript
From http://www.sitepoint.com/javascript-truthy-falsy/
The following values are always falsy:
- false
- 0 (zero)
- "" (empty string)
- null
- undefined
- NaN (a special Number value meaning Not-a-Number!)
All other values are truthy, including "0"
(zero in quotes), "false"
(false in quotes), empty functions, empty arrays ([]
), and empty objects ({}
).
Regarding why this is so, I suspect it's because JavaScript arrays are just a particular type of object. Treating arrays specially would require extra overhead to test Array.isArray()
. Also, it would probably be confusing if true arrays behaved differently from other array-like objects in this context, while making all array-like objects behave the same would be even more expensive.
Solution 2 - Javascript
You should be checking the .length
of that array to see if it contains any elements.
if (myCollection) // always true
if (myCollection.length) // always true when array has elements
if (myCollection.length === 0) // same as is_empty(myCollection)
Solution 3 - Javascript
> While []
equals false
, it evaluates to true
.
yes, this sounds bad or at least a bit confusing. Take a look at this:
const arr = []; if (arr) console.log("[] is truethy"); if (arr == false) console.log("however, [] == false");
In practice, if you want to check if something is empty,
then check the length
. (The ?.
operator makes sure that also null
is covered.)
const arr = []; // or null; if (!arr?.length) console.log("empty or null")
Solution 4 - Javascript
I suspect it has something to do with discrete math and the way a conditional (if then) works. A conditional has two parts, but in the instance where the first part doesn't exist, regardless of the second part, it returns something called a vacuous truth.
Here is the example stated in the wikipedia page for vacuous truths
"The statement "all cell phones in the room are turned off" will be true when no cell phones are in the room. In this case, the statement "all cell phones in the room are turned on" would also be vacuously true"
The wikipedia even makes specific mention of JavaScript a little later.
Solution 5 - Javascript
Also want to add, that all objects in JavaScript (arrays are objects too) are stored in memory as links and these links are always not null or zero, that's why Boolean({}) === true
, Boolean([]) === true
.
Also this is the reason why same objects (copied by value not the link) are always not equal.
{} == {} // false
let a = {};
let b = a; // copying by link
b == a // true
Solution 6 - Javascript
As in JavaScript, everything is an object so for falsy and empty, I use the below condition:
if(value && Object.keys(value).length){
// Not falsy and not empty
}
else{
// falsy or empty array/object
}