150

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.

isherwood
  • 52,576
  • 15
  • 105
  • 143
racl101
  • 3,322
  • 4
  • 33
  • 33
  • 7
    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. – dandavis Oct 02 '13 at 20:26
  • 2
    Why don't you use `myCollection.length > 0`? – Steve Oct 02 '13 at 20:26
  • 1
    @Steve - that won't work if `myCollection` happens to be `null` or `undefined`. You need to use `if(myCollection && myCollection.length > 0)`. – Ted Hopp Oct 02 '13 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. – Steve Oct 02 '13 at 20:37
  • 3
    possible duplicate of [javascript empty array seems to be true and false at the same time](http://stackoverflow.com/questions/5491605/javascript-empty-array-seems-to-be-true-and-false-at-the-same-time) – bummi Jan 02 '15 at 23:04
  • guys you don't need to use `myArray.length > 0` because if length is 0, it will return 0 which is false and if it returns any other length greater than 0 it will be true by default. – Kunok Aug 28 '17 at 13:18

6 Answers6

171

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.

yiwei
  • 3,692
  • 9
  • 33
  • 53
Barmar
  • 669,327
  • 51
  • 454
  • 560
  • 44
    If you test the expression `[] == false` it evaluates to `true`. – m.rufca Apr 24 '18 at 18:06
  • 4
    @m.rufca See https://stackoverflow.com/questions/5491605/empty-arrays-seem-to-equal-true-and-false-at-the-same-time – Barmar Apr 24 '18 at 19:29
  • there is a handful table showing unexpected situations using `==` comparator in the link you posted. I commented just to be careful when expecting true or false evaluation. – m.rufca Apr 24 '18 at 21:10
  • Yes, there's a difference between writing `if(xxx)` and `if(xxx == true)`, and between `if(!xxx)` and `if(xxx == false)`. You should only use the `==` forms when you know the value is a boolean (and even then many programmers consider it poor style). – Barmar Apr 24 '18 at 21:15
  • 7
    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. – Esa Lindqvist May 14 '18 at 13:03
  • @EsaLindqvist Questions about language design are not really on-topic, they're opinion-based. But arrays are just objects that happen to have a few special properties (e.g. `length`). Objects are all truthy. – Barmar May 14 '18 at 15:27
  • @Barmar yes but there must be some reasoning behind it. That's the question. – Esa Lindqvist May 15 '18 at 15:59
  • @EsaLindqvist It's probably because arrays are objects, objects are all truthy, and they didn't want to make a special case for them. – Barmar May 15 '18 at 17:24
  • There already are special cases for String, Number and Boolean wrapper objects aren't there? – Esa Lindqvist May 16 '18 at 04:44
  • 1
    Maybe, because those are required to act like the primitive objects. But Javascript doesn't have primitive arrays. – Barmar May 16 '18 at 04:46
  • How about "null" and "undefined"? – MrBoJangles Mar 16 '22 at 22:24
41

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)
DevlshOne
  • 8,177
  • 1
  • 27
  • 36
11

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")
bvdb
  • 19,466
  • 7
  • 98
  • 111
  • 3
    Woah, that [_optional chaining operator_ `?.`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining). That seems pretty new (and useful). Thanks for my TIL. – Константин Ван Jan 27 '21 at 23:58
  • 1
    @КонстантинВан I guess it needs a warning about compatibility. :-) Thank you for pointing that out. – bvdb Jan 28 '21 at 08:12
  • 1
    Why am I only now finding out about the optional chaining operator? and the related [Nullish coalescing operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) So good! Thanks – Dave Apr 14 '21 at 01:39
1

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.

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
Toni
  • 1,495
  • 4
  • 13
  • 22
ZloiGoroh
  • 386
  • 2
  • 9
0

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
}
Shivam Sharma
  • 1,012
  • 8
  • 28