When an empty array ([]
) is cast to a boolean in JavaScript it equals true
because it is an object, and all objects are cast to true
. This is due to the fact that object variables are merely references to the location of the object which is a truthy value.
Boolean([]); // true for ALL arrays
Boolean(new Array()); // same as above, true for ALL arrays
Boolean(new Date()); // true for ALL date objects
Boolean(new String()); // true for ALL string objects
Code language: JavaScript (javascript)
At first this might seem contradictory because an empty string (""
) evaluates to false
when cast to a boolean (Boolean("") === true
). But the reason is because an empty string is a primitive
, not an object
. If you create the string as a String
object then it will always evaluate to true
, just like with an Array
object.
Boolean("") // false, this is a string primitive
Boolean(new String()) // true, this is a String *object*
Code language: JavaScript (javascript)
So this behavior is strange indeed, but at least it is consistent in that all objects are cast to true
.
Another example of how JavaScript is at least consistently inconsistent:
Boolean(0) // false, this is a number primitive
Boolean(new Number(0)) // true, this is a Number *object)
Code language: JavaScript (javascript)
But this is where it gets weird… if you evaluate an empty array in a conditional without explicitly casting it to a boolean, then it will be false
!
[] == false // this is true!
[] === false // this is false, since it is a strict comparison
Boolean([]) === false // this is false
Code language: JavaScript (javascript)
This behavior is due to how comparisons are done in JavaScript. To compare []
with false
, the JavaScript engine must first convert the array to a primitive. It doesn’t convert it to a boolean, but rather it converts it to a number primitive.
[] == false // true
+[] // 0, which is false
+false // also 0
+[] == +false // true
Code language: JavaScript (javascript)
It definitely seems inconsistent that when using Boolean([])
the array is cast to a boolean, but when doing [] == false
it is cast to a number. But that is just how it is…
The Moral of The Story
So what is the takeaway here?
Well, you should always try to be explicit in your code about what you are actually trying to compare. It doesn’t really make sense to directly compare an array to a boolean
, or a number
, or anything else.
The only situation where it makes sense is you want to check if a variable is referencing the same object
as another variable:
let arr1 = [];
let arr2 = [];
arr1 === arr2; // false, they are different arrays
arr1 === arr1; // true, they are the same array
Code language: JavaScript (javascript)
Otherwise, if you are not checking the reference value of an object, you should explicitly convert it first to the appropriate value before making a comparison.
For example, are you wanting to check if the length
of an array is 0
? Then do that explicitly:
arr1.length === 0 // true, it is empty
+arr1 === 0 // also true, but don't do this! it isn't clear
Code language: JavaScript (javascript)
By being more explicit in your code you can make it more readable and reduce the chance of bugs popping up.
References
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures
Leave a Reply