-4

I found some interesting behavior and I'm wondering why it's the case.

var test = [null] // array with a single null element

> test == true
false

> test == false
true

> if(test) {console.log('true');}
'true'

Here's where it gets more interesting.

var test = [null, null]

> test == true
false

> test == false
false

> if(test) {console.log('true');}
'true'

Any idea why it behaves like this?

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Lfa
  • 1,069
  • 2
  • 10
  • 23
  • 1
    Comparing an array to a non-array with `==` has little practical use unless you consider this entertainment or you enjoy studying intricacies of type conversion rules in the ECMAScript spec. What is the point of this? – jfriend00 Aug 28 '15 at 15:52
  • That has been asked a few times. Search for truthy and falsy. `if (something not null, empty string, 0)` will always return true. As for the others, look at what the test.toString() returns and you will see why [null]==false is true and [null,null]==false is false – mplungjan Aug 28 '15 at 15:53
  • no wait we are doing some mess, now i read better, he try to compare a boolean to anything else, it's clearly alway false, and the condition give true everytime it didn't have '==' operator unless is undefined. – mautrok Aug 28 '15 at 15:58
  • 3
    If you really want to know the answer to this, then go study type conversion rules in the ECMAScript specification. The answer is all there. – jfriend00 Aug 28 '15 at 16:00
  • http://stackoverflow.com/questions/359494/does-it-matter-which-equals-operator-vs-i-use-in-javascript-comparisons?rq=1 – Xotic750 Aug 28 '15 at 16:02

1 Answers1

3

When == is used to compare things of different types, like an array ([null]) and false, it has specific steps it goes through, called the Abstract Equality Algorithm (quoted below) to try to coerce them to things that it can compare. (Because == is the "loose" equality operator.)

First it sees if either operand is null or undefined, but in this case neither is.

Then it sees if it's comparing a number and a string, but that's not true in this case either.

Then it seems if either operand is a boolean, which of course on of these is. Since one of them is a boolean, it does an abstract operation called ToNumber in the spec to convert the other one to a number and does another ==. (The Number function, when used as a function and not a constructor, is basically a wrapper for that abstract ToNumber operation.)

So

[null] == false

becomes

0 == false

...because ToNumber([null]) coerces its argument to a string (via ToPrimitive), getting "", and then converts that to 0.

So now == has something where one of the operands is a number. SO it converts the other one to a number as well. Number(false) is 0.

Thus, [null] == false is true.


So what about [null, null] == false? When converting [null, null] to a string, we get ",", which ToNumber can't turn into a valid number. So it converts it to NaN. One of the fun things about NaN is that it's a number, but it's never equal to anything else. So:

[null, null] == false 

becomes

NaN == false

becomes

NaN == 0

...which is false, because (again) NaN is never equal to anything.


Here's that Abstract Equality Algorithm:

  1. ReturnIfAbrupt(x).
  2. ReturnIfAbrupt(y).
  3. If Type(x) is the same as Type(y), then

    a) Return the result of performing Strict Equality Comparison x === y.

  4. If x is null and y is undefined, return true.

  5. If x is undefined and y is null, return true.
  6. If Type(x) is Number and Type(y) is String,
    return the result of the comparison x == ToNumber(y).
  7. If Type(x) is String and Type(y) is Number,
    return the result of the comparison ToNumber(x) == y.
  8. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
  9. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
  10. If Type(x) is either String, Number, or Symbol and Type(y) is Object, then
    return the result of the comparison x == ToPrimitive(y).
  11. If Type(x) is Object and Type(y) is either String, Number, or Symbol, then
    return the result of the comparison ToPrimitive(x) == y.
  12. Return false.
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • https://stackoverflow.com/questions/5491605/empty-arrays-seem-to-equal-true-and-false-at-the-same-time This is a good reference on JS == comparisons, specifically with arrays – Matt Aug 28 '15 at 16:04