220

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 should evaluate to false?

Also, Is this behavior consistent in all browsers? Or are there any gotchas there too? I observed this behavior in Google Chrome by the way.

7
  • 16
    arrays are objects, objects are truthy. just ask for array.length, if not zero, it will be truthy. when you explicitly convert to Boolean, the array turns into an empty string first, then the empty string turns into false. Commented Oct 2, 2013 at 20:26
  • 2
    Why don't you use myCollection.length > 0? Commented Oct 2, 2013 at 20:26
  • 2
    @Steve - that won't work if myCollection happens to be null or undefined. You need to use if(myCollection && myCollection.length > 0). Commented Oct 2, 2013 at 20:29
  • @TedHopp - of course... I was just pointing out that myCollection.length > 0 offers a boolean value that is doing what the OP asked for... he still needs to do the work from there. Commented Oct 2, 2013 at 20:37
  • 3
    possible duplicate of javascript empty array seems to be true and false at the same time Commented Jan 2, 2015 at 23:04

7 Answers 7

232

From http://www.sitepoint.com/javascript-truthy-falsy/

The following values are always falsy:

  • false
  • 0 (zero)
  • 0n (BigInt 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.

Sign up to request clarification or add additional context in comments.

13 Comments

If you test the expression [] == false it evaluates to true.
This doesn't really answer the question, which was WHY. Why is an empty array truthy, when an empty string is falsy? As a deliberate design decision this feels very poor.
Maybe, because those are required to act like the primitive objects. But Javascript doesn't have primitive arrays.
@EricDuminil I didn't know about BigInt when I wrote the answer 9 years ago. But I think it's enough to say that all forms of zero are falsey
|
57

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)

Comments

28
[]==false  // returns true

This evaluates to true, because of the Abstract Equality Algorithm as mentioned here in the ECMA Specification #Section 11.9.3

If you run through algorithm, mentioned above.

In first iteration, the condition satisfied is,

Step 7: If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

Hence the above condition transforms to -> [] == 0

Now in second iteration, the condition satisfied on [] == 0:

Step 9: If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.

[] is an object, henceforth, on converting to primitive, it transforms to an empty string ''

Hence, the above condition transforms to -> '' == 0

In third iteration, condition satisfied, is:

Step 5: If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.

As we know, empty string, '' is a falsy value, hence transforming an empty string to number will return us a value 0.

Henceforth, our condition, will transform to -> 0 == 0

In fourth iteration, the first condition is satisfied, where the types are equal and the numbers are equal.

Henceforth, the final value of the [] == false reduces to 0 == 0 which is true.

Hope this answers your question. Otherwise, you can also refer this youtube video

4 Comments

I've been hoping for this answer for almost a decade.
Finally an answer that references the language specification,
![] == false // returns true as well
Yes, @EliSherer, that's expected only. Focus on second iteration from the above algorithm, where object is converted to a primitive, (![]).toString() , it will internally, result to empty string, that is falsy value. Henceforth, false Which means, third and fourth iteration remains same, and result for above comment is true as well. Remember my friend, !([]==false) will be false ![]==false will be true
17

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")

3 Comments

Woah, that optional chaining operator ?.. That seems pretty new (and useful). Thanks for my TIL.
@КонстантинВан I guess it needs a warning about compatibility. :-) Thank you for pointing that out.
Why am I only now finding out about the optional chaining operator? and the related Nullish coalescing operator So good! Thanks
2

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.

https://en.wikipedia.org/wiki/Vacuous_truth#:~:text=In%20mathematics%20and%20logic%2C%20a,the%20antecedent%20cannot%20be%20satisfied.&text=One%20example%20of%20such%20a,Eiffel%20Tower%20is%20in%20Bolivia%22.

Comments

1

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
}

Comments

0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.