WTFJS: true != 'true' [duplicate] - javascript

MDC describes the == operator as follows:
If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible.
With this in mind, I would evaluate "true" == true as follows:
Are they of the same type? No
Is either operand a number or boolean? Yes
Can we convert both to a number? No (isNaN(Number("true")) // true)
Is either operand a string? Yes
Can we convert the other operand to a string? Yes (String(true) === "true" // true)
I've ended up with the strings "true" and "true", which should evaluate to true, but JavaScript shows false.
What have I missed?

Because "true" is converted to NaN, while true is converted to 1. So they differ.
Like you reported, both are converted to numbers, because at least true can be (see Erik Reppen's comment), and then compared.

The == comparison operator is defined in ECMA 5 as:
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).
So, "true" == true is evaluated as:
"true" == ToNumber(true) (via rule 7)
"true" == 1
ToNumber("true") == 1 (via rule 5)
NaN == 1
===> false

Acording to The Abstract Equality Comparison Algorithm
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
if one of the oprends is a boolean and other is not, boolean is converter to number 0 or 1. so true == "true" is false.

The equality operators (== and !=) use the Abstract Equality Comparison Algorithm to compare two operands.
"true" == true
Since "true" is String and true is Boolean, we need to return the result of "true" == Number(true) (step 7 in the algorithm), which is "true" == 1.
"true" == 1
Since "true" is String and 1 is Number, we need to return the result of Number("true") == 1 (step 5 in the algorithm). Number("true") returns NaN.
Now we have NaN == 1.
NaN == 1
Now both operands are of the same type (Number).
Acording to the algorithm, if both operands are Number and one of them is NaN, false is returned (step 1.c.i in the algorithm).

Explaining considering the scenario true == "true".
Straightway, the above returns false, however, our expectation was true
JavaScript uses Abstract Equality Comparison Algorithm, so according to the algorithm
true == "true"
// If one of the operands is Boolean, convert the Boolean operand to 1 if it is true and +0 if it is false
ConvertToNumber(true) == "true"
1 == "true"
// When the algorithm finds the above statements, it thinks that it needs to do one more conversion -
// "When comparing a number to a string, try to convert the string to a numeric value"
1 == ConvertToNumber("true)
1 == NaN
// Which returns false

Related

Can't understand the conditional execution flow [duplicate]

This question already has an answer here:
Javascript equality operators
(1 answer)
Closed 3 years ago.
A simple js snippet. Why does it always alert
'result is empty'
As per my understanding, if block should get executed since result!="" is true and alert
'result is not empty'.
<script>
var result = false;
if(result != "")
alert('result is not empty')
else
alert('result is empty')
</script>
It's because != does implicit type conversion. If you used the strict version, !==, it would do what you expect. But the loose version, !=, will convert both of those operands to numbers, and both "" and false convert to 0, so "" != false is false, because it ends up (through a series of convolutions) being 0 != 0.
This is laid out in detail in Abstract Equality Comparison algorithm in the specification:
ReturnIfAbrupt(x).
ReturnIfAbrupt(y).
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, then
return the result of the comparison x == ToPrimitive(y).
If Type(x) is Object and Type(y) is either String, Number, or Symbol, then
return the result of the comparison ToPrimitive(x) == y.
Return false.
As we can see from the above, if we start out with false and "", then:
We follow Step 8, convert false to 0, and start again with 0 != ""
We follow Step 6, convert "" to 0, and start again with 0 != 0
We follow Step 3 and get the result false (because we're doing !=, whereas the algorithm is defined in terms of ==).
In javascript two falsy things can be equal, as in this case, where result != "" yields false.
You need to use an strict comparison, i.e. !== to make the comparison. result !== "" yields true.
Javascript checks for truthy values.
false != ""
is false
false !== ""
is true so you can try it.

Javascript equality operators

In David Flanagan's Javascript guide, there is a statement:
the == operator never attempts to convert its operands to boolean
So here I did a little test:
var a = false;
var b = ""; // empty string
a == b; //returns true
Looking at Abstract Equality Comparison Algorithm there is a point:
e. If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.
How can x and y be both true if y is string data type (without conversion)?
What happens under the hood is
If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
Number(false) == ""
followed by
If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
Number(false) == Number("") -> 0 == 0
How can x and y be both true if y is string data type (without conversion)?
They are not both true, but after type coercion their values are equal.
the == operator never attempts to convert its operands to boolean
And that is correct, if you check the comparison algorithm you will find that types are never implicitly casted to Boolean.
References:
11.9.3 The Abstract Equality Comparison Algorithm
9.3 ToNumber

Why === faster than == in JavaScript? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
See these tests:
== vs ====
== vs ===
Here's what javascript has to do for ===:
If Type(x) is different from Type(y), return false.
If Type(x) is Undefined, return true.
If Type(x) is Null, return true.
If Type(x) is Number, then
If x is NaN, return false.
If y is NaN, return false.
If x is the same Number value as y, return true.
If x is +0 and y is −0, return true.
If x is −0 and y is +0, return true.
Return false.
If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.
If Type(x) is Boolean, return true if x and y are both true or both false; otherwise, return false.
Return true if x and y refer to the same object. Otherwise, return false.
And here's what it has to do for ==:
If Type(x) is the same as Type(y), then
If Type(x) is Undefined, return true.
If Type(x) is Null, return true.
If Type(x) is Number, then
If x is NaN, return false.
If y is NaN, return false.
If x is the same Number value as y, return true.
If x is +0 and y is −0, return true.
If x is −0 and y is +0, return true.
Return false.
If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false.
If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.
Return true if x and y refer to the same object. Otherwise, return false.
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 or Number 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 or Number,
return the result of the comparison ToPrimitive(x) == y.
Return false.
Notice that if Type(x) equals Type(y) then the operators do the same thing. However, if they aren't, then the == might have to do various conversions whereas === just returns false.
For the links you gave, the types that are being compared are actually the same, so the two operators should perform about equally. Differences here would be based on implementation details - since they do different things, they can be optimized for differently. Theoretically, since === does less, one would think it would always be faster, but that doesn't appear to be the case for certain builds of Firefox, at least if those benchmarks are accurate.
However, see the difference if the types are different. When doing "hi" === {} you get ~66 million ops/second, but for "hi" == {} you only have ~4 million ops/second.
JavaScript is a weakly typed language, so it will apply type coercion wherever possible.
Equals Operator
// These are true
new Number(10) == 10; // Number.toString() is converted
// back to a number
10 == '10'; // Strings gets converted to Number
10 == '+10 '; // More string madness
10 == '010'; // And more
isNaN(null) == false; // null converts to 0
// which of course is not NaN
The Strict Equality Operator
It works like the normal equality operator, except that strict equality operator does not perform type coercion between its operands.
"" === "0" // false
0 === "" // false
0 === "0" // false
false === "false" // false
false === "0" // false
false === undefined // false
false === null // false
null === undefined // false
" \t\r\n" === 0 // false
The above results are a lot clearer and allow for early breakage of code. This hardens code to a certain degree and also gives performance improvements in case the operands are of different types.
So === faster than == in Javascript
Here is good Reference
=== compares if the values and the types are the same.
== compares if the values are the same, but it also does type conversions in the comparison. Those type conversions make == slower than ===.

JavaScript truthiness in boolean to numbers comparison

I'm new to JavaScript and I'm trying to learn it from internet resources. While I'm aware that there will plenty of cr*p material, one thing most people seemed to agree is the truthiness of things in JS (just to give a example go here)
Now I found this odd thing in my experiments:
(true == 2) is false. why?
As far as I know, 2 is a non zero number, so it should be evaluated as true.
This is because when either operand of an equality operator is a number, in nearly all cases the other operand is converted to a number and then the result is compared. So you're ending up comparing 1 (converted from true) with 2, not true with true. The only exceptions to that rule are null, undefined, and objects whose default value (see off-topic below) is null or undefined; comparing a number to those returns false (even though Number(null) is 0; don't ask).
Details in the specification, Section 11.9.3: "The Abstract Equality Comparison Algorithm". This was the text of that section as of ES 5.1, but that link is to the currently editor's draft (which is what each year's snapshot specification is based on) and there have been several :
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.
NOTE: This step is replaced in section B.3.7.2.
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 BigInt and Type(y) is String, then
Let n be ! StringToBigInt(y).
If n is NaN, return false.
Return the result of the comparison x == n.
If Type(x) is String and Type(y) is BigInt, return the result of the comparison y == x.
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, BigInt, 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, BigInt, or Symbol, return the result of the comparison ? ToPrimitive(x) == y.
If Type(x) is BigInt and Type(y) is Number, or if Type(x) is Number and Type(y) is BigInt, then
If x or y are any of NaN, +∞𝔽, or -∞𝔽, return false.
If ℝ(x) = ℝ(y), return true; otherwise return false.
Return false.
Note: The !s in the above are not negations, they indicate that the following abstract operation never results in an abrupt completion. Details in this article about reading the spec.
If you wanted to check that they were both truthy or both falsy, you could use the bang (!) or double-bang (!!) idiom to coerce them both to booleans:
var a = true,
b = 2;
alert(a == b); // "false", 1 !== 2
alert(!!a == !!b); // "true", true === true
alert(!a == !b); // "true", false === false
a = false;
b = 0;
alert(a == b); // "true", 0 === 0
alert(!!a == !!b); // "true", false === false
alert(!a == !b); // "true", true === true
...but usually using == or != with booleans isn't ideal. But it does come up.
I tend to use the double-bang, but in JavaScript there's no reason to over the bang. (There's an argument for the double over the single in some other languages, though it's a weak one related to consistency with if (!!x). In JavaScript you never need the double-bang in the if (x) case, so...)
(Off-topic: The default value of most JavaScript objects is a string, though frequently one like "[object Object]" that ends up being NaN if you convert it to a number; but constructor functions can override that behavior via valueOf and toString. The default value of host objects is up to the host environment.)
The boolean true constant is promoted to a number, that being 1.
With non-strict comparison (==) if the operands are not of the same type, they will be casted/coerced and strictly compared, with first preference being to numbers if either operand is a number or boolean (MDN).
So true == 2 evaluates to Number(true) === 2 which is 1 === 2, which is false.
Of course you can always force things to compare as you want them to, which is explicit and can solve hard-to-find problems later on:
true === Boolean(2) is true.

JavaScript type casting

Consider empty JavaScript array:
var a = [];
alert(a == false); // shows true
alert(!a); // shows false!
How to explain this?
What are the rules?
From http://forums.whirlpool.net.au/archive/966449:
a == false:
In this case, the type of the left-hand side is object, the type of the right-hand side is 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.
See §11.9.3 of the ECMAScript spec for all the gory details.
(!a):
In this case Javascript converts the object to the boolean true, then inverts it, resulting in false.
The ! operator checks whether its operand is "falsy".
The following are true:
!false
!0
!null
!NaN
!undefined
!""
The == operator checks for loose equality, which has nothing to do with falsiness.
Specifically, a == b 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
The == operator when one of the operands if Boolean, type-converts the other to Number.
[] == 0;
Is equivalent to:
0 == 0;
You can see the complete details of The Abstract Equality Comparison Algorithm on the specification.
As you can see, an empty array object, when converted to Number, produces 0:
+[]; // 0
Number(0);
This is really because its toString method produces an empty string, for example:
[].toString(); // ""
+""; // 0
Number(""); // 0
When comparing an object to a primitive value via the == operator, the object coerces into an primitive value itself (number or string). In this case [] coerces into 0, then false coerces into 0:
[] == false
0 == false
0 == 0
which is true.
The ! operator coerces into boolean and then inverts the value. [] into boolean is true (like with any object). Then invert to become false
![]
!true
false
Not sure if this answers the question, but there is a new library for getting around all of Javascript's Typecasting weirdnesses:
Typecast.js
In a sentence, Typecast solves all the simple problems, so you can focus on the big ones. Typecast fixes what's wrong with Javascript by creating a complete platform for strongly-typed variables in Javascript.

Categories