Let’s go through each instances in this tweet, but first, let’s refresh our minds on some key topics to demystifying this weird expressions.
BOOLEAN
The boolean type has only two values: true and false.
Conversion to boolean can be performed explicitly...
When an explicit conversion is made (using “Boolean” keyword; without quotes) or the JS engine implicitly coerces a value, object, expression
the following values returns “false” (without quotes)
0, null, undefined, NaN, ""
Boolean(0) == false
Boolean(0) === false
Same for null, undefined, NaN or empty string (“”).
Every other value is true.
Now, we have a ‘little’ insight on how Boolean works.
Logical NOT Operator (!)
This basically, calls Boolean on a value and then invert the boolean value returned by the Boolean operator.
For Example: !null will return true.
Below is how the semantics is evaluated during runtime..
UnaryExpression : ! UnaryExpression
1. Let expr be the result of evaluating UnaryExpression.
2. Let oldValue be ToBoolean(GetValue(expr)).
3. ReturnIfAbrupt(oldValue).
4. If oldValue is true, return false.
5. Return true.
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
1. ReturnIfAbrupt(x).
2. ReturnIfAbrupt(y)...
1. 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.
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).
return the result of the comparison ToPrimitive(x)==y
12. Return false
It is important to state here that NaN(Not a Number) is not equal to any other value, not even itself. Yes, that’s our it works
===========================
On line with code:
[] == ![]; -> true
To evaluate the above expression, we follow the steps below:
Step 1: Identify the Operators in the expression
== and !
Logical NOT (!) will be executed before Abstract Equality Comparison (==)
Step 3: Apply the conditions as stated in the specification until the operators are exhausted.
let x = [], y = ![]
y = !Boolean([]) -> !true -> false
Now we are done with Logical NOT Operator and y is false.
Next we Apply the == operator which is a binary operator and will compare two operands.
[] == false
Type(x) = typeof([]) -> “object"
Type(y) = typeof(false) -> "boolean"
Now we know the types of the operands.
Since Type(y) is a boolean, Rule/Condition 9 is the first to hold:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
Which is: x == ToNumber(y) -> [] == Number(false) -> [] == 0
[] == 0
Going down the Rule/Condition, condition 11 holds
Type(x) -> typeof([]) -> “object” and
Type(y) -> typeof(0) -> “number”
We apply rule 11 and we have:
ToPrimitive(x) == y.
x.toString() -> [].toString() -> “” empty string
The link below describes how ToPrimitive works.
ecma-international.org/ecma-262/6.0/#…
We are done with Rule/Condition 11, which finally results to:
“” == 0
Type(x) is String and Type(y) is number. Then, evaluate to:
ToNumber(x) == y
Which further evaluates to:
Number(x) == y -> Number(“”) == 0
Since Number(“”) -> 0
We then have:
0 == 0 -> true
!!"false" == !!"true"; -> true
Remember that when a logical NOT operator is used in an expression, it first attempts to convert the expression at the right hand side to a Boolean value.
Therefore, Boolean(”false”) -> true
!!true -> !(!true) -> !false -> true
!!true -> !(!true) -> !false -> true
true == true -> true
"b" + "a" + +"a" + "a"; -> "baNaNa"
Here, having the understanding that the + operator can act as arithmetics operator, concatenation operator or as a unary operator is very important.
See picture below:
NaN === NaN; -> false
This holds because the value NaN is not equal to any other value, not even itself.
0.1 + 0.2 !== 0.3 -> true
Here, it’s not entirely a thing of Javascript weird parts, rather it has to do with how floating-point values are formatted and stored in the computer. Computer Scientists will understand better.
0.1 + 0.2 === 0.30000000000000004
0.30000000000000004 !== 0.3 -> true
When dealing with arithmetic expressions involving floating-point values the result is not always 100% correct.
Reference:
docs.oracle.com/cd/E19957-01/8…
P.S: My points here may not be entirely correct. Please feel free to like, retweet and make corrections (if any…)
Thank you!
+"a" - > Number("a") - > NaN
Please review my (javascript) points here.
Thank you!