14
if([] == false) alert('empty array is false');
alert(+[]) // alert 0
if([]) alert('empty array is true');

They both will run the alert

Demo

Jonathan de M.
  • 9,721
  • 8
  • 47
  • 72
  • 2
    Seems like it might be some weird type coercion going on with `==`. If you try to cast a boolean like `!![]` you get `true`, if you use the `===` operator as in `[] === false` then it won't alert anything. – elclanrs Dec 10 '12 at 11:00
  • document.write(">"+[].toString()+"<") – mplungjan Dec 10 '12 at 11:02

3 Answers3

18

It's because of type coercion of the == (equality) operator.

An empty array is considered truthy (just like an empty object), thus the second alert is called.

However, if you use ([] == false), your array is coerced to its string representation* which is "" which then is considered as a falsy value, which makes the condition true thus triggering the first alert too.

If you want to avoid type coercion, you have to use the === (identity) operator which is the preferred and by the famous Douglas Crockford promoted way to compare in javascript.

You can read more on that matter in this exhaustive answer.

*(Object.prototype.toString is called on it)

EDIT: fun with JS-comparison:

NaN == false // false
NaN == true  // also false
NaN == NaN   // false

if(NaN)      // false
if(!NaN)     // true

0  == '0'     // true
'' == 0       // true
'' == '0'     // false !

This shows you the real "power" of Comparison with == due to the strange rules mentioned in bfavarettos answer.

Community
  • 1
  • 1
Christoph
  • 50,121
  • 21
  • 99
  • 128
  • More precisely, `Object.prototype.toString` gets called on the array instance with the result of `""` (for the conditional case). – jAndy Dec 10 '12 at 11:03
  • @jAndy that's true, i wanted to keep it simple, but good you added the comment;) – Christoph Dec 10 '12 at 11:04
  • 2
    @Lightness well, I'm no native speaker, so this might not make perfect sense, what i just wanted to say is that you might need to evaluate his very convinced opinions for yourself. – Christoph Dec 10 '12 at 12:01
18

Both current answers here are correct, but I'd like to add a more detalied explanation based on the language specification. The reason for the apparently contradictory outcomes is that if statements and equality comparisons are evaluated differently.

In the case of an if(expression) statement, the expression is evaluated and then converted to the boolean type (§ 12.5). Arrays are Objects, and when an Object is converted to Boolean, the result is always true (§ 9.2).

Equality comparisons with == follow a different set of rules, detailed on § 11.9.3. The comparison may require multiple type conversions, until both operands are the same type. The order of the operands is also important. According to that algorithm, we can see that the comparison [] == false is actually a four-step operation:

  1. There is a Boolean involved, so it's converted to a Number first (step 7 of the algorithm). So it becomes:

    [] == 0
    
  2. Then the array is converted to its primitive value (see § 9.1 and § 8.12.8), and becomes an empty string (step 9). So:

    "" == 0
    
  3. When comparing a String to a Number, the String is converted to Number first (step 5, following the rules described on § 9.3.1):

    0 == 0
    
  4. Now that we have two Numbers, the comparison evaluates to true according to step 1.c.iii.
bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • +1 For doing the homework, note however that there still is the problem with some conversions like `""` to `0` which cannot be easily explained but are the keypoint for those oddities and the lack of transitivity of the equality operator like with `''`,`0` and `'0'`. – Christoph Dec 10 '12 at 14:06
  • Thanks @Christoph. Added a link to section 9.3.1, where `"" -> 0` is explained. – bfavaretto Dec 10 '12 at 16:31
  • What I understood, in `if([] == false)` `[]` and `false` are converted to a number so +[] = 0 and +false = 0 and are equal, and in `if([])` `[]` is converted to an object which is converted to a bool and object are always true. Is that right? – Jonathan de M. Dec 11 '12 at 01:52
  • 1
    @JonathandeM. Almost. In `if([] == false)`, `false` is converted to `0` directly; `[]` is converted to string first (something like `[]+"" // ""`), then `""` is converted to `0`. In `if([])`: arrays *are* objects, so the array isn't converted to an object, it already is one. – bfavaretto Dec 11 '12 at 03:08
3

There is a difference between evaluating a value as a boolean, and comparing it to true or false.

Whe using the == operator, the values are converted so that the types correspond. The [] value converted to the empty string "", and converting that in turn to a boolean gives false, so [] == false becomes true.

Evaluating [] as a boolean value will return true, because it is not a 'falsy' value, i.e. 0, false, null, "", NaN or undefined.

Christoph
  • 50,121
  • 21
  • 99
  • 128
Guffa
  • 687,336
  • 108
  • 737
  • 1,005