Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is "0" == [] false? [duplicate]

Tags:

javascript

console.log( 0 == '0' );     // true
console.log( 0 == [] );     // true 
console.log( [] == '0' );    // false

Why does JavaScript evaluate the expression like this?

like image 857
TheChetan Avatar asked Oct 30 '17 12:10

TheChetan


People also ask

Why is 0 == [] in JS?

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.

Does the integer 0 == 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.

Is 0 truthy or Falsy?

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 .

Does === return false?

Note that === never causes type coercion, but checks for correct types first and yields false if they are not equal!


2 Answers

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"));
like image 122
Jamiec Avatar answered Nov 01 '22 11:11

Jamiec


/*
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

like image 34
Renan Muniz Avatar answered Nov 01 '22 09:11

Renan Muniz