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?
Advertisement
Answer
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:
- ReturnIfAbrupt(
x
). - ReturnIfAbrupt(
y
). If Type(
x
) is the same as Type(y
), thena) Return the result of performing Strict Equality Comparison
x
===y
.If
x
isnull
andy
isundefined
, returntrue
.- If
x
isundefined
andy
isnull
, returntrue
. - If Type(
x
) is Number and Type(y
) is String,
return the result of the comparisonx
== ToNumber(y
). - If Type(
x
) is String and Type(y
) is Number,
return the result of the comparison ToNumber(x
) ==y
. - If Type(
x
) is Boolean, return the result of the comparison ToNumber(x
) ==y
. - If Type(
y
) is Boolean, return the result of the comparisonx
== ToNumber(y
). - If Type(
x
) is either String, Number, or Symbol and Type(y
) is Object, then
return the result of the comparisonx
== ToPrimitive(y
). - If Type(
x
) is Object and Type(y
) is either String, Number, or Symbol, then
return the result of the comparison ToPrimitive(x
) ==y
. - Return
false
.