5

Was just playing around with nodejs and chrome's console when I tested this:

[] == true // false
![] == true // false
!![] == true // true

How come? Isn't it wrong?

Hugo Mota
  • 11,200
  • 9
  • 42
  • 60
  • 3
    This is why you don't use implicit unless needed. – Cole Tobin Jun 14 '12 at 02:32
  • @ColeJohnson—considering the `!` operator converts the LHS to boolean and the RHS is already boolean, the results will be identical. And for the second two, the two algorithms ([Abstract Equality](http://es5.github.com/#x11.9.3) and [Strict Equality](http://es5.github.com/#x11.9.6) Comparison Algorithm) do exactly the same steps, so there is zero benefit to using one over the other. There may be good reason to do `[] == 0` and not `[] === 0` since the former may be true or false (depending on the members in the arra), but the later will always be false. – RobG Jun 14 '12 at 03:43

3 Answers3

7

See the ECMAScript standard:

11.4.9 Logical NOT Operator ( ! )

The production UnaryExpression : ! UnaryExpression is evaluated as follows:

  1. Let expr be the result of evaluating UnaryExpression.
  2. Let oldValue be ToBoolean(GetValue(expr)).
  3. If oldValue is true, return false.
  4. Return true.

9.2 ToBoolean

The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:

  • undefined → false
  • null → false
  • Boolean → The result equals the input argument (no conversion).
  • Number → The result is false if the argument is +0, -0, or NaN; otherwise the result is true.
  • The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
  • Object → true

An array is an Object.

Kijewski
  • 25,517
  • 12
  • 101
  • 143
  • but, weirdly enough, empty objects are neighter true or false D: – Hugo Mota Jun 14 '12 at 02:40
  • @hugo_leonardo: Empty objects are always `true` when evaluated as a Boolean. –  Jun 14 '12 at 02:42
  • `a = {}; a == true; a == false;` both comparisons returned false in my console... – Hugo Mota Jun 14 '12 at 02:44
  • 3
    @hugo_leonardo: The `==` operator does not cast its operands to boolean values –  Jun 14 '12 at 02:46
  • @hugo_leonardo just as am not i am says: `!` takes the boolean value (as per 2nd bullet point of 11.4.9). `==` does not do such a thing (see section 11.9.3). – Kijewski Jun 14 '12 at 02:49
  • @amnotiam I guess this explains it ~ so the only one doing the casting is the `!` operator. Thank you (: – Hugo Mota Jun 14 '12 at 02:54
  • 2
    @hugo_leonardo: Study the *Abstract Equality Comparison Algorithm* http://es5.github.com/#x11.9.3 You'll see that when the two operands are of different types, the conversion is almost always a *toNumber* conversion. An Object gets a *toPrimitive* conversion. In the case of an Array, I believe it first gets *toString*, followed by the *toNumber*. An empty array is therefore converted to `""`, then to `0`. A boolean gets converted *toNumber*, so `false` is `0`. `0 == 0` –  Jun 14 '12 at 02:55
  • ...yes, the `!` takes it straight to Boolean, which is `true`, but then negated to `false`, so `false == false`. –  Jun 14 '12 at 02:56
  • @amnotiam— in the first example, the RHS is convereted using *toNumber* but the LHS is an object, so it uses *toPrimitive*, which will be to an empty string so it becomes `'' == 1` which evaluates to false. Note that `[1] == true` returns true as it's converted to `'1' == 1`. – RobG Jun 14 '12 at 03:54
  • @RobG: Right, I wasn't differentiating between an Object and an Array. I was just showing that in the case of an empty Array object, it's converted toString `""`, then ultimately toNumber as the conversions continue. –  Jun 14 '12 at 11:40
2

It has to do with how the browser handles implicit conversions in JS.


As [] is an empty array, it evaluates to false:
[] == true
false == true


However, noting it, will turn the object into a boolean with a value of false:
![] == true
false == true

However, boolean([]) will return true.


However, noting that, will turn it into a boolean with the value of !false:
!![] == true
!false == true
true == true


This is why implicit conversions arn't recomended unless needed:
"1" == true
true == true

"1" === true
false
Cole Tobin
  • 9,206
  • 15
  • 49
  • 74
  • it's the same on node.js (edit: well, off course its the same engine. but it's the same on IE's console too) – Hugo Mota Jun 14 '12 at 02:31
  • @zneak that was a mistake, fixed – Cole Tobin Jun 14 '12 at 02:31
  • `Boolean([])` -> true, try it. – FatalError Jun 14 '12 at 02:32
  • An empty array does not evaluate to false: Boolean([]) // true – Trevor Jun 14 '12 at 02:33
  • but if `Boolean([])` evaluates to true (I expected that too, because it's an object), how come `[] == true` evaluates to false? – Hugo Mota Jun 14 '12 at 02:34
  • 3
    @hugo_leonardo, because implicit casts and explicit casts are not the same. Welcome to Javascript, where casts are not isomorphic. – zneak Jun 14 '12 at 02:35
  • Wow, that's confusing. `[] == false` evaluates to true, but `[] || 1` evaluates to `[]`. Sometimes I just don't get javascript... – FatalError Jun 14 '12 at 02:38
  • 1
    @FatalError: There's no way around the fact that the `==` algorithm is a little complex. The first thing to always remember is that `==` is not doing a Boolean evaluation of its operands. When people assume that, it becomes understandably confusing. –  Jun 14 '12 at 02:47
0

[] == true is false because [] is not equal to true, just like "some string" is also not equal to true.

![] == true is false because [] evaluates to a true value when used in a conditional statement:

if([]) console.log('[]');
if(![]) console.log('![]');
// the result will be '[]' because [] will evaluate to true
// in a conditional even though it doesn't equal true

Another thing that may help you to think about it is ![] == false will be true.

!![] == true is true because !! converts anything to a true or false value based on whether it would be true or false in a conditional statement. So if(obj) and if(!!obj) will always have the same result.

Nathan Wall
  • 6,426
  • 2
  • 22
  • 23
  • I personally use the terms "equal" for `==` and "identical" for `===`, when a distinction between the two is important. Just my 2 cents. – zneak Jun 14 '12 at 05:07