As the title states, why does:
> !!1=="1"
equal
True
and
> !!2=="2"
equal:
False
Likewise, why does > "1"==true equal true and > "2"==true equal false
I'm baffled. Are these just bugs in JS or what's going on here?
As the title states, why does:
> !!1=="1"
equal
True
and
> !!2=="2"
equal:
False
Likewise, why does > "1"==true equal true and > "2"==true equal false
I'm baffled. Are these just bugs in JS or what's going on here?
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.
!!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)isBoolean, return the result of the comparisonToNumber(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)isNumberandType(y)isString, return the result of the comparisonx == 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.
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.
tldr; this is due to the [ToNumber] conversions in the == operator algorithm.
The first step is to simplify the expression. Since !!x=="x" is parsed like (!!x)=="x" and !!a_truthy_expression -> true, the actual relevant expression for the equality is
!!1=="2" -> true=="1" -> Boolean==String
!!2=="2" -> true=="2" -> Boolean==String
So then looking at the rules for 11.9.3 The Abstract Equality Comparison Algorithm and following along with the application yields
Rule 6 - If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
which results in Number==String or 1=="1" and 1=="2", respectively1. Then the rule
Rule 7 - If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
is applied which results in Number==Number or 1==1 and 1==2, respectively1; the latter is clearly false.
Rule 1 - If Type(x) is the same as Type(y), then [by c.iii.] If x is the same Number value as y, return true [else return false].
(The same algorithm explains the String==Boolean case when the complementing rules are applied.)
1To see the [ToNumber] rule applied, consider:
+false -> 0
+true -> 1
+"1" -> 1
+"2" -> 2
Its a precedence operator problem.
The ! operator is an unary operator. That means the left side must be an expression or a boolean evaluable section. See Javascript MDN.
!!1==1 is not necessary !!(1==1)
!!2==2 is not necessary !!(2==2)
I think that these expressions should be consistent if the equal operator has more precedence than ! operator. But if we consider the opposite, evaluating first negations we have:
!!1 == 1
!1 -> false
!!1 -> true
!!1 == 1
And with the two
!!2==2
!2 -> false
!!2 -> true
(!!2) == 2 -> false
That is because the ! operator has precedence over == operator
!!1 is equal to true, and "1" is equal to true ("0" is false, so is every other string). So !!1 == "1" evaluates to true == true, which of course returns true.
!!2 is also equal to true. As I mentioned earlier, "2" is not "1", so it's false. Therefore, we have true == false, which of course returns false.
If you want to see if 2 (a number) is equal to "2" (a string representation of a number), then all you have to do is 2 == "2", which evaluates to 2 == 2, which is true. The difference is that we're not comparing a boolean against a boolean. We're comparing a number against a number.
Basically, putting !! in front of a number converts to a boolean, which forces JavaScript to cast your string to a boolean instead of a number.
Because "1" may be considered as "true" when you do equality check, not identity, but "2" - can't.