console.log( 0 == '0' ); // true
console.log( 0 == [] ); // true
console.log( [] == '0' ); // false
Why does JavaScript evaluate the expression like this?
In JavaScript “0” is equal to false because “0” is of type string but when it tested for equality the automatic type conversion of JavaScript comes into effect and converts the “0” to its numeric value which is 0 and as we know 0 represents false value. So, “0” equals to false.
C does not have boolean data types, and normally uses integers for boolean testing. Zero is used to represent false, and One is used to represent true. For interpretation, Zero is interpreted as false and anything non-zero is interpreted as true.
In JavaScript, a truthy value is a value that is considered true when encountered in a Boolean context. All values are truthy unless they are defined as falsy. That is, all values are truthy except false , 0 , -0 , 0n , "" , null , undefined , and NaN .
Note that === never causes type coercion, but checks for correct types first and yields false if they are not equal!
JavaScript will try to coerce types when using double equals operator (==
). Exact details in spec: sec 11.9.3: Abstract Equality Comparison Algorithm.
Example 1:
console.log( 0 == '0' ); // true
JavaScript coerces the string to the number 0
, so 0 == 0
.
Example 2:
console.log( 0 == [] ); // true
An empty array's "ToPrimitive" value is zero, when comparing to a number. So this one reduces to 0 == 0
.
Example 3:
console.log( [] == '0' ); // false
console.log( [] == '' ); // true
While the first one looks quite similar to the previous example, neither side is a number. At first glance this appears to be a truthy
comparison, BUT []
is not one of the eight falsy
values.
Demonstrating that []
is truthy, but ''
is falsy:
console.log( [] ? true : false ); // true
console.log( '' ? true : false ); // false
In any sane language, the above two statements would imply that [] == ''
would be false
. But as we saw earlier, that isn't the case in JavaScript!
INEXPLICABLY, []
converts to false
when using ==
:
console.log( [] == true ); // false
console.log( [] == false ); // true
Conclusion: both sides are converted to booleans, but NOT by the "normal" "truthy/falsy" rule (which would convert []
to true
, because it is not one of the eight falsy values). Instead, []
converts to false
when using ==
:
console.log( [] == '0' ); // `false == true`, so false
console.log( [] == '' ); // `false == false`, so true
Example 4:
console.log( [0] == '' ); // false
console.log( [1] == '' ); // false
This could EITHER indicate that the length of the array (1
), which is "truthy", is compared to ''
, which is "falsy", so true == false
, which is false
. OR it could indicate that no type conversion is appropriate, which is case (10) in the spec, so false
. BUT see example 5, which doesn't seem to fit either possibility.
Example 5:
console.log( [0] == '0' ); // true
console.log( [0] == '1' ); // false
console.log( [1] == '1' ); // true
console.log( [1] == '0' ); // false
console.log( [2] == '2' ); // true
console.log( [1] == '2' ); // false
Surprisingly, an array that contains one number, apparently is converted to that number, when comparing to a non-empty string. This then goes to the rule for comparing a number to string, which converts the string to a number. So we are comparing either (0
or 1
or ..) to (0
or 1
or ..).
Is this an ambiguity in the spec? Differs between different implementations?
Testing done at https://www.webtoolkitonline.com/javascript-tester.html
on 2020-Oct-27, in Chrome on a Windows 10 pc, using alert
instead of console.log
.
Example 6:
If all the above doesn't convince you to never use ==
again, consider this:
var a = [];
console.log( a == a ); // true
BUT:
console.log( [] == [] ); // false
None of the 9 type conversion rules in the spec apply, so this is case 10: they aren't the same object, even though neither of them has any contents. They are two different instances of an empty array.
In all, this is why its generally safer to use triple equals, which checks type and equality.
A handy illustration (for the cases that test truthiness) below:
function truthyOrFalsy(val) {
return val ? "Truthy" : "Falsy";
}
console.log("empty array:", truthyOrFalsy([]));
console.log("number zero:", truthyOrFalsy(0));
console.log("string with a zero character:", truthyOrFalsy("0"));
/*
If Type(x) is Number and Type(y) is String,
return the result of the comparison x == ToNumber(y).
*/
console.log( 0 == '0');
/*
If Type(x) is either String or Number and Type(y) is Object,
return the result of the comparison x == ToPrimitive(y).
*/
console.log( 0 == [] );
/*
If Type(x) is Object and Type(y) is either String or Number,
return the result of the comparison ToPrimitive(x) == y.
*/
console.log( [] == '0');
source: http://es5.github.io/#x11.9.3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With