JavaScript string resolves to false - javascript

Why both of these resolve to false:
console.log("potato" == false); //false
console.log("potato" == true); //false
Because what I know when using == loose comparison, JS coerces the operand. Since in JS, non-empty string should be true, why do above return false above ?

There needs a clarification about the == operator. From ECMA-262 Section 11.9.3 the rule6, rule7 and later rule4 determines your result
rule 6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
rule 7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
rule 4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
In your context, false and true will be converted to 0 and 1, while the 'potato' will be converted to NaN, the comparison expression's value is always false.
"potato" == false // => "potato" == 0 => NaN == 0
"potato" == true // => "potato" == 1 => NaN == 1
Similarly, in '' == true comparison, '' will be converted to 0 while true will be converted to 1, the expression is false.
'' == false // => 0 == 0
'' == true // => 0 == 1
Due to the non-intuitive implementation of ==,=== is encouraged to use in comparison.

You mean Truthy and Falsy Values:
if ("potato") {
console.log("true")
}
But here you compare the String "potato" and a true, JavaScript will try to cast to a comparable thing and that is not the case when you compare the two values you have.

Related

Why does this code runs correctly with loose equality than with strict equality?

I tried to code the snippets with both strict equality and loose equality to count the total number of truthy values in the given array.
The code runs correctly with the loose equality
let array = [0, '0', true, 100, false, NaN];
countTruthy(array);
function countTruthy(array){
let count = 0 ;
for (let element of array){
if (element == (null || undefined || NaN || false || 0 || '')){ //comparing with loose equality
continue;
}
console.log(element);
count++
}
console.log (`The total truthy in the array is : ${count}`);
}
While the code gives incorrect count with strict equality.
let array = [0, '0', true, 100, false, NaN];
countTruthy(array);
function countTruthy(array){
let count = 0 ;
for (let element of array){
if (element === (null || undefined || NaN || false || 0 || '')){//Using the strict equality
continue;
}
console.log(element);
count++
}
console.log (`The total truthy in the array is : ${count}`);
}
I also tried the
console.log(undefined === undefined);
Why am I getting the wrong count with strict equality while correct count with loose equality?
I also know there is efficient way to write the same code. So please give suggestions only for the above issues I am facing.
When you use a chain of ||s, the whole expression will evaluate to the first truthy value, if there is one - otherwise, it will evaluate to the final (falsey) value. So
(null || undefined || NaN || false || 0 || '')
is equivalent to
('')
With strict equality, none of the array items are the empty string, so all pass the test.
With loose equality, only 0 and false are == to the empty string.
console.log(
0 == '',
false == ''
);
With Abstract Equality Comparison:
For 0 == '': When a number is compared against a string on the right, the string gets converted to a number, and 0 == 0 is true
If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
For false == '': When a boolean is compared against a string on the right, the boolean is converted into a number first:
If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
Then the string is converted into a number:
If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
and 0 == 0 is true.
I would just like to add that your code does not actually count the truthy values correctly - there are 3 truthy values in your array ("0", true, 100).
The problem comes from equating NaN in both loose and strict equality. NaN is always false when compared to anything, even:
NaN === NaN; //false
NaN == NaN; //false
That's why your code counts 4 values instead of 3 using loose equality.
A better way to check if a value is truthy is just to have Javascript convert it to a boolean:
function countTruthy(array){
let count = 0 ;
for (let element of array){
if (!element)
{
continue;
}
count++;
}
return count;
}

String coercion into boolean

Boolean("a")
returns true in the Browser console.
So why
"a" == true
returns false?
How the == operator functions on certain types is defined in the ECMAScript specifications. It is as followed:
7.2.13 Abstract Equality Comparison
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
If Type(x) is the same as Type(y), then
Return the result of performing Strict Equality Comparison x === y.
If x is null and y is undefined, return true.
If x is undefined and y is null, return true.
If Type(x) is Number and Type(y) is String, return the result of the comparison x == ! ToNumber(y).
If Type(x) is String and Type(y) is Number, return the result of the comparison ! ToNumber(x) == y.
If Type(x) is Boolean, return the result of the comparison ! ToNumber(x) == y.
If Type(y) is Boolean, return the result of the comparison x == ! ToNumber(y).
If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y.
Return false.
Now we can apply them to this the cases above. Which first converts the boolean into a number and then attempts to convert the string into a number (which is parsed as NaN):
"a" == true
// Case 7 (true --> 1)
// =>"a" == 1
// Case 5 ("a" --> NaN)
// => NaN == 1
=> false
You need to see how Javascripts works.
"a" is a string.
true is a boolean.
So "a" is not equal to true.
Doing Boolean("a"), is like to ask "Is "a" ?". This bizarre question will answer true if what you put in (so here "a") is [implicitly something not null or empty].
You shouldn't use this Boolean function in this context, the result will never be what you think (Boolean("false") will return true for example)
See here for more information: https://stackoverflow.com/a/264037/6532640
// Boolean("a") is equal to asking if "a" == "a" so it will return true
console.log(Boolean("a"));
// "a" == true can't return true, because a string and a boolean can't be equal
console.log("a" == true);
// for the same reason this will return false too
console.log("true" == true);
// and this will return true
console.log("true" == true.toString());
//-----------------------------------------
// If we talk about numbers, there are different rules.
// In javascript you will be able to convert a string with
// numbers to a number and vice versa
// this is why "1" is equal to 1
console.log("1" == 1);
// considering the interest in trying to use every kind of
// variable in var, they described some basical rules
// for example adding a number to a string will work
// like every language
// this is why here you will obtain "11" as result
var one = "1";
console.log(one+1);
// in this case - doesn't work with strings, so our var one
// will be considered as an integer and the result will be 1
var one = "1";
console.log(one-1+1);

Type coercion in JavaScript , how is the conversion done?

This is because the equality operator == does type coercion, meaning that the interpreter implicitly tries to convert the values before comparing.
Looked into this
but, 0 == '' , I dont understand why it returns true. Can any one explain? what is 0 converted to ? and what is '' converted to to return true ?
When abstractly comparing a string and a number, regardless of the order, the string will be converted ToNumber() for the comparison:
4. If Type(x) is Number and Type(y) is String,
return the result of the comparison x == ToNumber(y).
5. If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
In the case of 0 == "", ToNumber("") results in 0, which is exactly the other value:
0 == "" // becomes...
0 == 0 // becomes...
true
Note: You can see how the internal-onlyToNumber() handles different values by using the Number() constructor without new:
console.log(Number(""))
// 0

0 vs '0' with boolean operators

0 == false and '0' == false are both 'true'
However, (true && 0) is 'false', while (true && '0') is 'true'.
Why?
The abstract comparison (==) rules are described in ES5 11.9.3 while the rules for logical operators (&&) are described in ES5 11.11.
In short, == is just more complex than &&. Where && just uses the internal ToBoolean() to evaluate its operands, == has various conditions that may result in the use of ToBoolean(), ToNumber(), and/or ToPrimitive().
(0 == false) == true:
7. If Type(y) is Boolean, return the result of comparison x == ToNumber(y)
ToNumber(false) === 0, so 0 == 0, so true.
('0' == false) == true:
This also passes through step 7, resulting in '0' == 0.
Then, starting over at the top, it reaching step 5:
5. If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
ToNumber('0') === 0, so again 0 == 0, and again true.
!!(true && 0) == false
&& simply returns the 1st operand if it's falsy (ToBoolean(...) === false), or the 2nd operand.
It's strictly (true && 0) === 0.
And, when used as an if condition, the result (0) will as well be passed through ToBoolean(...) and ToBoolean(0) === false.
!!(true && '0') == true
Again, this returns the 2nd operand, '0'.
This time, however, ToBoolean('0') === true as '0' is a non-empty String, making it truthy.
Also, if you want simpler comparison rules, use strict comparison (===, 11.9.6).
'0' (or any non-empty string) is 'truthy' in JS. The == operator, however, does some strange type-coercion which is why many prominent JS figures including Crockford highly discourage it. This is a good example of why you should avoid it, it takes the string '0' and coerces it into a falsey value.
Here's a link that explains this process:
http://webreflection.blogspot.com/2010/10/javascript-coercion-demystified.html
If Type(x) is Boolean, return the result of the comparison
ToNumber(x) == y: false == 0 and true == 1 but true != 2
So even stranger than your example is this:
('1' == true) // true
('2' == true) // false!

How does Type Coercion in Javascript in the case of object to boolean?

To the best of my knowledge, (x == false) should do the same thing as !x, as both of them try to interpret x as a boolean, and then negates it.
However, when I tried to test this out, I started getting some extremely strange behavior.
For example:
false == [] and false == ![] both return true.
Additionally
false == undefined and true == undefined both return false, as does
false == Infinity and true == Infinity and
false == NaN and true == NaN.
What exactly is going on here?
http://jsfiddle.net/AA6np/1/
It's all here: http://es5.github.com/#x11.9.3
For the case of false == []:
false is converted to a number (0), because that is always done with booleans.
[] is converted to a primitive by calling [].valueOf().toString(), and that is an empty string.
0 == "" is then evaluated by converting the empty string to a number, and because the result of that is also 0, false == [] is true.
For the case of false == ![]:
The logical not operator ! is performed by returning the opposite of ToBoolean(GetValue(expr))
ToBoolean() is always true for any object, so ![] evaluates to false (because !true = false), and therefore is false == ![] also true.
(false == undefined) === false and (true == undefined) === false is even simpler:
false and true are again converted to numbers (0 and 1, respectively).
Because undefined cannot be compared to a number, the chain bubbles through to the default result and that is false.
The other two cases are evaluated the same way: First Boolean to Number, and then compare this to the other number. Since neither 0 nor 1 equals Infinity or is Not A Number, those expressions also evaluate to false.
The abstract equality algorithm is described in section 9.3 of the specification.
For x == y where x = false and y = []:
Nope. Types are not equal.
Nope, x is not null.
Nope. x is not undefined.
Nope, x is not a number
Nope, x is not a string.
Yes, x is a boolean, so we compare ToNumber(x) and y.
Repeat the algorithm, x=0 and y=[].
We end at step 8:Type(x) == number. and Type(y) == object.
So, let the result be x == ToPrimitive(y).
ToPrimitive([]) == ""
Now, repeat the algorithm again with x=0 and y="". We end at 4: "return the result of the comparison x == ToNumber(y)."
ToNumber("") == 0
The last repetition of the algorithm ends at step 1 (types are equal). By 1.c.iii, 0 == 0, and true is returned.
The other results can be obtained in a similar manner, by using the algorithm.
false == []
Using == Javascript is allowed to apply conversions. The object will convert into a primitive to match type with the boolean, leaving an empty string. The false will convert into a number 0. The compares the empty string and the number 0. The string is converted to a number which will be 0, so the expression is "true"
![]
Javascript converts the object to the boolean true, therefore denying true ends being false.
false == undefined true == undefined
false == Infinity and true == Infinity
false == NaN and true == NaN
Again a bit of the same! false is converted to 0, true to 1. And then, undefined is converted to a number which is... NaN! So false in any case
I would recommend to use === !== as much as you can to get "expected" results unless you know very well what you are doing. Using something like Boolean(undefined) == false would also be nice.
Check ECMAScript specifications for all the details when converting stuff.

Categories

Resources