I believe that's because plain {}[true]
is parsed as an empty statement block (not an object literal) followed by an array containing true
, which is true
.
On the other hand, applying the !
operator makes the parser interpret {}
as an object literal, so the following {}[true]
becomes a member access that returns undefined
, and !{}[true]
is indeed true
(as !undefined
is true
).
As per the Operator precedence rules, logical !
has higher priority over ==
. So, in both the cases, !!
is evaluated first.
Note: Truthiness of various objects have been explained in this answer of mine.
First Case
!!1 == "1"
!1
will be evaluated to false
, since 1
is considered Truthy. Negating again we get true
. So the expression becomes
true == "1"
Now, the coercion rules kick in as you have used ==
operator, which evaluates as per the The Abstract Equality Comparison Algorithm defined in ECMAScript 5.1 Specification,
6. If Type(x)
is Boolean
, return the result of the comparison ToNumber(x) == y
.
So, true
will be converted to a number, which is 1 as per ToNumber
algorithm for Boolean values. Now the expression becomes
1 == "1"
Now,
4. If Type(x)
is Number
and Type(y)
is String
,
return the result of the comparison x == ToNumber(y)
.
So, "1"
will be converted to a number and that will give 1, as per the ToNumber
algorithm. That is why it shows true
in the first case.
Second Case
The same rules are applied here.
!!2 == "2"
becomes
true == "2"
then
1 == "2"
which becomes
1 == 2
which is not true
, that is why the second case prints false
.
Best Answer
It's the way coercion works.
The first step of coercion is to convert any non primitive types to primitive types, then using a set of rules convert the left, right or both sides to the same type. You can find these rules here.
In your case
[] == true
, would pass through these 4 steps:[] == true
[] == 1
"" == 1
0 == 1
Whereas based on operator precedence the
!
in![] == true
is executed first so the expression is converted tofalse == true
which is obviouslyfalse
.You can try the live demo by Felix Kling to better understand how the sameness operator works.
In more words:
The value
![]
isfalse
, because[]
is an Object (arrays are objects) and all objects, not includingnull
, are truthy. So any array, even if it is empty will always be a truthy, and the opposite of a truthy is alwaysfalse
. The easiest way to check if a value is a truthy is by using!!
.When you are using a loose comparison (using
==
instead of===
) you are asking the JavaScript engine to first convert the values into the same type and then compare them. So what happens is the values get converted according to a set of rules, once they are the same type, they get compared though the same process as a strict equality check (===
). The first change that[]
goes through is to get converted to a string, the string version of an empty array is an empty string""
, the empty string is then converted to a number, the numeric value of an empty string is0
, since the numeric value oftrue
is1
and0
!=1
, the final output isfalse
.