This question already has answers here:
Why is "0" == [] false? [duplicate]
(4 answers)
Closed 2 years ago.
If 0 (as a digit) equals to 0 as a string, and 0 equals to an empty list, why 0 as a string is not equal to an empty list (from the moment that 0 as a digit equals to 0 as a string)?
> 0 == '0'
true
> 0 == []
true
> '0' == []
false
To understand the results of your code, you need to understand how == equality operator works in the following cases:
When both operands are of same type, return the result of strict equality comparison ===
If one operand is a number and other is a string, convert the string operand to a number
If any or both operands are non-primitive, convert non-primitive operand to a primitive value
Keeping the above mentioned points in mind, lets see how each comparison is processed:
0 == '0'
This evaluates to true because '0' is converted to a number and then strict equality comparison is performed since both operands have the same type after the conversion of '0' to a number.
0 == []
returns true because when any operand of the == operator is non-primitive, it is converted in to a primitive value. Empty array when converted into a primitive value, results in an empty string. So after this conversion, you have 0 == ''. Now one operand is a number and other is a string. Empty string is then converted to a number which results in 0 leading to the comparison of 0 == 0 which evaluated to true.
'0' == []
this returns false because empty array is converted to a primitive value which is an empty string. When [] is converted to an empty string, types of both operands ('0' == '') are same, so strict equality comparison is done which returns false.
For details, see Ecmascript Spec: 7.2.15: Abstract Equality Comparison
In JavaScript, double equals does not mean strictly equal to, whereas tripple equals === does. In the former cases a conversion is made as a result of the types involved, whereas no such available conversion (which results in semi-equality) exists in the latter case.
JavaScript is designed that way.
In 0 == '0'
== converts '0' to 0 because the right operand is a number
So what happens is it checks 0 == 0 which is true.
Tips use === called strick equality comparison to check, which will treat 0 as a number and '0' as a string.
0 == []
In Javascript empty array is treated as a falsy, while 0 is always false and 1 truth.
So == compares false == false which is true. Once again use strict equity sign ===
'0' == []
Here since [] is not a number Javascript won't care to convert '0' to 0 which means the comparison is comparing string and array which will won't be true.
. You have 3 cases.
when you write '0' == 0 , the Value of '0' in utf-8 is 0 hence
false ==false is true
String is basically a list in python when you write '0' you are basically making a list with an element '
'0' ie '0' ==['0'] and not [ ] hence true==false is false
while when you write 0==[ ] every value with 0 is false and the empty list returns the Boolean value of number of elements in the list which is False for 0 hence false ==false is true
Related
I was playing around with JSconsole and found something strange. The value of "0" is false
"0" == false
=> true
The value of false when used in ternary returns the second value
false ? 71 : 16
=> 16
However the value "0" which equals false when used in ternary returns the first value.
"0" ? 8 : 10
=> 8
However, if you use 0 as the value, it returns the second value
0 ? 4 : 5
=> 5
0 == "0"
=> true
I'm afraid this doesn't make sense to me.
Non-empty string is considered as truth value in conditional statements, conditional expressions and conditional constructs.
But when you compare a string with a number with ==, some conversion will take place.
When comparing a number and a string, the string is converted to a
number value. JavaScript attempts to convert the string numeric
literal to a Number type value. First, a mathematical value is derived
from the string numeric literal. Next, this value is rounded to
nearest Number type value.
And == don't have the Transitive Property of Equality:
you can't say if a == b, b == c, then a == c.
An example will be:
"0" == false // true
false == "\n" //true
and guess the result of "0" == "\n"? Yes, the result is false.
"0" is a string of length>0 which is true. Try
0 ? 8 : 10
and see. It will return 10.
== does type conversion and hence when you do
"0" == false
it returns true. When you do
0 == "0" //true
It also returns true as again type conversion is taking place. Even though one is a number and the other one is a string it returns true. But if you use ===, no type conversion is done and 0 === "0" will return false.
A nice explanation of == & === is given here.
From the docs:
The equality operator(==) converts the operands if they are not of the same type, then applies strict comparison.
The identity operator(===) returns true if the operands are strictly equal with no type conversion.
I'm afraid this is an example of why you should use === - plain old == performs type conversion. Try
"0"===false
JavaScript leads to tons of WTFs.
Check out "Javascript WTF" on YouTube...
Essentially, you are requesting a conversion from string to boolean.
This is defined as "string is not empty".
Whereas you assumed that javascript does string -> int -> boolean if the string happens to contain a number.
It's sensible. But these automatic conversions lead to programming errors, which is why I prefer typesafe languages (with compile time type checking) for larger projects.
For fun, try these:
("0" * 1) ? 71 : 16
("0" + false) ? 71 : 16
I have compared some strings and numbers to see the result as true and false
"dfdf" > 1
false
"dfdf" > 99
false
"dfdf" > 9999
false
"dfdf" > 99999
false
1> ''
true
1> '545'
false
1> '545d'
false
1> '555'
false
1> 'ddfdf'
false
9999 > 'dfsdfadf'
false
I have tried few different combinations in the code as you can see but got the mixed result and want to know how exactly the comparison works in javascript.
another addition which is even more confusing
"dasfads" > "dasfdsf"
false
"abc" > "a"
true
"abc" > "agf"
false
"abcf" > "agf"
false
Comparing a string to a number will force the string data to evaluate into a number value. If the string data is not convertible to a numerical value it will return a NaN number to the given comparison.
Since NaN is not comparable nor equal to anything at all, not even to another NaN
NaN == NaN > false
The 'greater than' or 'smaller than' NaN comparison will have to return false both ways. Because that's the only correct answer, nothing can be greater nor smaller than the value you don't have. Therefore both claims are false. e.g.: 0 > NaN and 0 < NaN > false.
But keep in mind that comparing two strings of data such as:
"98A" > "999" will return a comparative false,
whereas:
"9A" > "999" will return true
Which is a very powerful thing to know, because knowing this (two strings will be compared by alphabetical order of magnitude) you are able to compare time data without taking the burden of converting those values to numbers and directly go with:
"09:32:28" > "09:31:59" > true
And luckily "PM" > "AM" > true by pure (linguistic) chance.
It is attempting to cast the string to a number.
In the console, if you do
x = +''
then x will be set to 0. 1 > 0 is true.
For all the other ones, if you do something like
x = +'dfdf'
then x will be set to NaN (not a number), and any comparison with it will return false.
There are 2 types of comparison available when using JavaScript,
The standard equality operators (== and !=) use the Abstract Equality Comparison Algorithm to compare two operands. If the operands are of different types, it will attempt to convert them to the same type before making the comparison, e.g., in the expression 5 == '5', the string on the right is converted to Number before the comparison is made.
The strict equality operators (=== and !==) use the Strict Equality Comparison Algorithm and are intended for performing equality comparisons on operands of the same type. If the operands are of different types, the result is always false so 5 !== '5'.
So if you want to know what is happening there, JavaScript is trying to convert the string into a Number and then do comparison, however, since they are not a number, which is always converted to NaN, and comparison with NaN will be equal to false.
Link for details:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators
String Vs String
The comparison is done character by character when you are comparing strings. First different character found in both string will be compared using their char codes. (Note: Chars after that will be ignored.)
>> "a".charCodeAt(0)
97
>> "}".charCodeAt(0)
125
>> "}" > "a"
true
>> "-}" > "a"
false
String Vs Number
Any time a string is compared with a number the string is converted into an integer and then both are compared. If the string can't be converted into a number, then it returns false. (Note: NaN, Nothing can be compared against NaN. Any comparison with NaN will return false)
>> 'dfsdfadf' > 999999 // Can't be converted to integer, hence false
false
>> 'd' > 9999999999 // Can't be converted to integer, hence false
false
>> '' == false // '' is empty string which is 0 or false
true
>> 1 > '' // '' is false,0 explained in prev case
true
if([] == false) alert('empty array is false');
alert(+[]) // alert 0
if([]) alert('empty array is true');
They both will run the alert
Demo
Both current answers here are correct, but I'd like to add a more detalied explanation based on the language specification. The reason for the apparently contradictory outcomes is that if statements and equality comparisons are evaluated differently.
In the case of an if(expression) statement, the expression is evaluated and then converted to the boolean type (§ 12.5). Arrays are Objects, and when an Object is converted to Boolean, the result is always true (§ 9.2).
Equality comparisons with == follow a different set of rules, detailed on § 11.9.3. The comparison may require multiple type conversions, until both operands are the same type. The order of the operands is also important. According to that algorithm, we can see that the comparison [] == false is actually a four-step operation:
There is a Boolean involved, so it's converted to a Number first (step 7 of the algorithm). So it becomes:
[] == 0
Then the array is converted to its primitive value (see § 9.1 and § 8.12.8), and becomes an empty string (step 9). So:
"" == 0
When comparing a String to a Number, the String is converted to Number first (step 5, following the rules described on § 9.3.1):
0 == 0
Now that we have two Numbers, the comparison evaluates to true according to step 1.c.iii.
It's because of type coercion of the == (equality) operator.
An empty array is considered truthy (just like an empty object), thus the second alert is called.
However, if you use ([] == false), your array is coerced to its string representation* which is "" which then is considered as a falsy value, which makes the condition true thus triggering the first alert too.
If you want to avoid type coercion, you have to use the === (identity) operator which is the preferred and by the famous Douglas Crockford promoted way to compare in javascript.
You can read more on that matter in this exhaustive answer.
*(Object.prototype.toString is called on it)
EDIT:
fun with JS-comparison:
NaN == false // false
NaN == true // also false
NaN == NaN // false
if(NaN) // false
if(!NaN) // true
0 == '0' // true
'' == 0 // true
'' == '0' // false !
This shows you the real "power" of Comparison with == due to the strange rules mentioned in bfavarettos answer.
There is a difference between evaluating a value as a boolean, and comparing it to true or false.
Whe using the == operator, the values are converted so that the types correspond. The [] value converted to the empty string "", and converting that in turn to a boolean gives false, so [] == false becomes true.
Evaluating [] as a boolean value will return true, because it is not a 'falsy' value, i.e. 0, false, null, "", NaN or undefined.
As far as I know in JavaScript !! is supposed to normalize a boolean value converting it to true or false from some other type. This would mean that the "0" converts to boolean true. On the other hand if I compare it with false it turns out that it is in fact false (as the result of the comparison is true). What rule am I missing here. I have tested it in IE and Opera.
The == operator checks for loose equality, which has nothing to do with truthiness.
Specifically, it will convert to operands to numbers, then compare the numbers.
Strings containing numbers convert to the numbers that they contain; booleans convert to 0 and 1.
Objects are converted by calling valueOf, if defined.
Thus, all of the following are true:
"1" == 1
"0" == false
"1" == true
"2" != true
"2" != false
({ valueOf:function() { return 2; } }) == 2
({ valueOf:function() { return 1; } }) == true
In the first case, a non-empty string is equivalent to true.
In the second case, because one operand is a boolean, both operands are converted to numeric values. I believe false converts to the numeric value 0 and the string "0" also converts to a numeric 0, resulting in 0 == 0 which is true.
Check out the Mozilla reference for operator behavior.
For the first expression, section 9.2 of ECMA-262 defines an abstract operation ToBoolean internally used by the logical NOT operator. It says:
String
The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
For the second expression, JavaScript will perform type coercion when it attempts to compare these values of different data types. Douglas Crockford says that this is a misfeature. It would be false if you had used === instead of ==. The rules are rather complex, so you should directly look in section 11.9.3 of ECMA-262 for the details.
Can anyone explain why the following two statements both evaluate as true?
[] == false
and
!![]
This question is purely out of curiosity of why this happens and not about how to best test if an array is empty.
The first one:
[] == false
The == operator does type conversion to its operands, in this case the both sides are converted to Number, the steps taken on the Abstract Equality Comparison Algorithm would be:
object == boolean
object == number
string == number
number == number
In code:
[] == false; // convert false to Number
[] == 0; // convert [] to Primitive (toString/valueOf)
"" == 0; // convert "" to Number
0 == 0; // end
The second comparison, [] is converted to primitive, their valueOf and toString methods are executed, but since valueOf on Array objects, returns the object itself (is inherited from Object.prototype), then the toString method is used.
At the end as you see, both operands are converted to Number, and both yield zero, for example:
Number([]) == 0;
Number(false) == 0;
And empty array produces zero when converted to Number because its string representation is an empty string:
[].toString(); // ""
And an empty string converted to Number, yields zero:
+""; // 0
Now, the double negation (!![]) produces true because all object instances are truthy:
![]; // false, [] is truthy
!![]; // true, negation
The only values that are falsey are:
null
undefined
0
NaN
"" (an empty string)
false
Anything else will produce true when converted to Boolean.
See also:
JavaScript Coercion Tool
[] == false
In this case, the type of the left-hand side is object, the type of the right-hand side is boolean. When object is compared to (== The Abstract Equality Comparison) boolean, Javascript first converts the boolean to a number, yielding 0. Then it converts the object to a "primitive", yielding the empty string "". Next it compares the empty string to 0. The empty string is converted to a number, yielding 0, which is numerically equal to the 0 on the right-hand side, so the result of the entire expression is true.
Ref:
http://es5.github.com/#x11.9.3
11.9.3 The Abstract Equality Comparison Algorithm
!![]
In this case Javascript converts the object to the boolean true, then inverts it, resulting in false.