16 Oct 2016 - by 'Maurits van der Schee'
What does the following expressions evaluate to?>  &&  == false true
Yes, it is "true"! If you don't believe me, try it. The question that is addressed in this post is: "Really? Why?!"Empty array evaluates to true
Let's test a few script languages to see what they evaluate empty array to:$ nodejs -e 'console.log(?"true":"false")' true $php -r 'print (?"true":"false");' false $ perl -e 'print (()?"true":"false")' false $ ruby -e 'print (?"true":"false")' true $ python -c 'print ("true" if  else "false")' false
As you can see the empty array in Ruby also evaluates to true, when used as a boolean expression. Other languages choose the (in my opinion) more logical "false" value to evaluate to. When we replace the empty array with "true" the expression behaves as expected:> true && true == false false
It almost seems as if in this case the empty array is not evaluated to "true". That can't be the case or can it?Operator precedence
I tried the following to find out whether or not this had to do with operator precedence:> ( && ) == false true >  && ( == false) true
But since both evaluate to true, I think we can rule operator precedence out. We have to dig a little deeper.Logical operator evaluation
I got the feeling it had something to do with the way script languages evaluate logical expressions. Instead of returning true or false most scripting languages (PHP excluded) return the first "falsy" (evaluates to false) or the second "truthy" (evaluates to true) argument of the "and" expression. You can see that here:> 0 && 1 0 > 2 && 3 3 Now let's see whether that is the case by replacing the "" by a "0" (zero): > 0 && 0 == false 0 > (0 && 0) == false true > 0 && (0 == false) 0 The above results may make you think it has anything to do with operator precedence, but we already proved that that was not the case. So somehow if we replace "" (empty array) with "0" (zero) we get correct results. Your head may be spinning now, but we expected the initial expression to evaluate to "" (empty array), because of the implementation of the "&&" (and) operator, that returns the first "falsy" argument it encounters. Since zero does not behave as the empty array the behavior seems to be unrelated to the way logical operators are evaluated. Comparison operator evaluation
So, let's approach it from the other side now. The only way we can construct the result "true" is when the "==" (comparison) operator fails to convert correctly to the type of the left or right hand side of the comparison expression. Let's try all possible paths:> Boolean()==Boolean(false) false > Number()==Number(false) true > String()==String(false) false > Object()==Object(false) false
You would expect the first to happen (or the last), because that seems the logical way to convert both sides to the same type. Apparently this is not true and the comparison expression between an object and a boolean is evaluated as a numerical comparison (which is unrelated to both the left and the right side). Don't you believe me? Read on.EcmaScript 6 standard
Let's see what the EcmaScript 6 standard states on "Equality Comparison":The comparison x == y [...] is performed as follows: [...] If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
It states (as the first matching step of the comparison algorithm) that comparison with a boolean on the right hand side should be done by converting that boolean to a number, just like we expected from our analysis.Conclusion
Now that I studied the standard I was able to come up with a similar case. Do you understand why this one fails as well?> "0" && "0" == false true