javascript comparison crises - javascript

I came across the following and was unable to grasp the reason, can anyone explain please?
var foo = [0];
console.log(foo == !foo); // true
console.log(foo == foo); // true

The second comparison is simple to explain: foo is equal to itself.
The first one, however, is a bit tricky: foo is an array, which is an object, which evaluates to true when coerced to boolean. So !foo is false. But foo on the left side of the comparison is not being converted to boolean. Both operands are actually converted to numbers during the equality comparison. This is how it evaluates:
[0] == false
[0] == 0
"0" == 0
0 == 0
true
According to MDN, on comparisons with the equality operator ==:
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
I know this explanation sounds superficial. It's actually much more complicated than that, but the basic steps are the ones I listed above. You can see the details on the ECMA-262 specification, particularly on sections 9 and 11.9.

You should use "===" and "!==" instead of "==" and "!="
More explanations there:
Which equals operator (== vs ===) should be used in JavaScript comparisons?
http://net.tutsplus.com/tutorials/javascript-ajax/the-10-javascript-mistakes-youre-making/

Related

What is happening in this loose equality comparison of 2 empty arrays

I am struggling with understanding how this snippet works on a basic level
if([] == ![]){
console.log("this evaluates to true");
}
Please help me understand where I got it wrong. My thinking:
First there is operator precedence so ! evaluates before ==.
Next ToPrimitive is called and [] converts to empty string.
! operator notices that it needs to convert "" into boolean so it takes that value and makes it into false then negates into true.
== prefers to compare numbers so in my thinking true makes 1 and [] is converted into "" and then 0
Why does it work then? Where did I get it wrong?
Why does it work then?
TLDR:
[] == ![]
//toBoolean [1]
[] == !true
[] == false
//loose equality round one [2]
//toPrimitive([]); toNumber(false) [3]
"" == 0
//loose equality round two
//toNumber("") [4]
0 === 0
true
Some explanations:
1)
First there is operator precedence so ! evaluates before ==
Negating something calls the internal toBoolean method onto that "something" first. In this case this is an Object (as Arrays are Objects) and for that it always returns true which is then negated.
2)
Now it's up to loose equalities special behaviour ( see Taurus answer for more info) :
If A is an Object ( Arrays are Objects ) and B is a Boolean it will do:
ToPrimitive(A) == ToNumber(B)
3)
toPrimitive([])
ToPrimitive(A) attempts to convert its Object argument to a primitive value, by attempting to invoke varying sequences of A.toString and A.valueOf methods on A.
Converting an Array to its primitive is done by calling toString ( as they don't have a valueOf method) which is basically join(",").
toNumber(false)
The result is 1 if the argument is true. The result is +0 if the argument is false. Reference
So false is converted to +0
4)
toNumber("")
A StringNumericLiteral that is empty or contains only white space is converted to +0.
So finally "" is converted to +0
Where did I get it wrong?
At step 1. Negating something does not call toPrimitive but toBoolean ...
The accepted answer is not correct (it is now, though), see this example:
if([5] == true) {
console.log("hello");
}
If everything is indeed processed as the accepted answer states, then [5] == true should have evaluated to true as the array [5] will be converted to its string counterpart ("5"), and the string "5" is truthy (Boolean("5") === true is true), so true == true must be true.
But this is clearly not the case because the conditional does not evaluate to true.
So, what's actually happening is:
1. ![] will convert its operand to a boolean and then flip that boolean value, every object is truthy, so ![] is going to evaluate to false.
At this point, the comparison becomes [] == false
2. What gets into play then is these 2 rules, clearly stated in #6 in the specs for the Abstract Equality Comparison algorithm:
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)
At this point, the comparison becomes [] == 0.
3. Then, it is this rule:
If Type(x) is Object and Type(y) is either String or Number,
return the result of the comparison ToPrimitive(x) == y.
As #Jonas_W stated, an array's ToPrimitive will call its toString, which will return a comma-separated list of its contents (I am oversimplifying).
At this point, the comparison becomes "" == 0.
4. And finally (well, almost), this rule:
If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
An empty string converted to a number is 0 (Number("") == 0 is true).
At this point, the comparison becomes 0 == 0.
5. At last, this rule will apply:
If Type(x) is the same as Type(y), then
.........
If Type(x) is Number, then
.........
If x is the same Number value as y, return true.
And, this is why the comparison evaluates to true. You can also apply these rules to my first example to see why it doesn't evaluate to true.
All the rules I quoted above are clearly stated here in the specs.
First, realize that you are comparing two different types of values.
When you use ![] it results in false. You have code (at core it results in this):
if([] == false)
Now the second part: since both values are of different type and you are using "==", javascript converts both value type into string (to make sure that they have same type). It starts from left.
On the left we have []. So javascript applies the toString function on [], which results in false. Try console.log([].toString())
You should get false on the left as string value. On the right we have boolean value false, and javascript does the same thing with it.
It use the toString function on false as well, which results in string value false.
Try console.log(false.toString())
This involves two core concepts: how "==" works and associativity of "==" operator - whether it starts from left or right.
Associativity refers to what operator function gets called in: left-to-right or right-to-left.
Operators like == or ! or + are functions that use prefix notation!
The above if statement will result in false if you use "===".
I hope that helps.

Javascript ES6. Difference between === and Object.is [duplicate]

This question already has answers here:
Object.is vs ===
(6 answers)
Closed 5 years ago.
We know what the difference between == and === is - basically, === prevents Javascript engine to convert one of the parameter for making both parameters of the same type. But now, in ES6, came a new operator - Object.is which is a bit confusing (or maybe === is now confusing..)
From Mozila website (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness) we can see the difference:
Sameness Comparisons:
x y == === Object.is
+0 -0 true true false
NaN NaN false false true
So, for me, looks like Object.is is even more strict in comparing parameters, if so, question raises - how unstrict was === (called "Strict Equality") :)
From the article you linked:
When to use Object.is versus triple equals
Aside from the way it treats NaN, generally, the only time Object.is's special behavior towards zeros is likely to be of interest is in the pursuit of certain meta-programming schemes, especially regarding property descriptors when it is desirable for your work to mirror some of the characteristics of Object.defineProperty. If your use case does not require this, it is suggested to avoid Object.is and use === instead. Even if your requirements involve having comparisons between two NaN values evaluate to true, generally it is easier to special-case the NaN checks (using the isNaN method available from previous versions of ECMAScript) than it is to work out how surrounding computations might affect the sign of any zeros you encounter in your comparison.
Via MDN:
This is also not the same as being equal according to the === operator. The === operator (and the == operator as well) treats the number values -0 and +0 as equal and treats Number.NaN as not equal to NaN.

null and undefined inconsistent comparison

I'm curious to know why
null == undefined
returns true but
null >= undefined
returns false
Is the inclusion of the greater than operator coercing the values differently?
tl;dr The >= ends up coercing both arguments to numbers in this case: undefined gets coerced to NaN while null gets coerced to 0, which aren't equal. For ==, the spec explicitly defines that null == undefined is true.
The values do, in fact, get coerced in both cases (in a sense, at least - the case with == is special). Let's consider them one at a time, with the help of the spec.
The algorithm for the >= operator uses the "Abstract Relational Comparison Algorithm", which is shared by other relational operators. From the description in the spec, we see that the algorithm does the following:
Converts the arguments to primitives (which null and undefined already are).
Checks if the arguments are Strings (which they are not).
If they are not Strings, the algorithm converts the arguments to numbers (see steps 3.a. and 3.b.) and performs the comparison with the results.
The last point is the key. From the ToNumber table, we see that undefined gets coerced to NaN, and the algorithm considers any comparison with NaN as being falsy (see steps 3.c. and 3.d.). Thus, null >= undefined is false.
For the other case, ==, the story is actually much simpler: the spec explicitly states that null == undefined is true as part of the "Abstract Equality Comparison Algorithm" (see steps 2. and 3.). Thus, null == undefined is true.
In JS == operator coerces values to same type to compare, so 1=="1" is true. Use === operator for exact type matching

What Are the Semantics of Javascripts If Statement

I always thought that an if statement essentially compared it's argument similar to == true. However the following experiment in Firebug confirmed my worst fears—after writing Javascript for 15 years I still have no clue WTF is going on:
>>> " " == true
false
>>> if(" ") console.log("wtf")
wtf
My worldview is in shambles here. I could run some experiments to learn more, but even then I would be losing sleep for fear of browser quirks. Is this in a spec somewhere? Is it consistent cross-browser? Will I ever master javascript?
"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 either operand is a string, the other one is converted to a string."
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Comparison_Operators
So the first one does:
Number(" ")==Number(true)
While the second one is evaluated like this:
if(Boolean(" ")==true) console.log("wtf")
I am guessing that it is the first part that is a problem, not the second.
It probably does some weird casting (most likely, true is cast to a string instead of " " being cast to a boolean value.
What does FireBug return for Boolean(" ") ?
JavaScript can be quirky with things like this. Note that JavaScript has == but also ===. I would have thought that
" " == true
would be true, but
" " === true
would be false. The === operator doesn't do conversions; it checks if the value and the type on both sides of the operator are the same. The == does convert 'truthy' values to true and 'falsy' values to false.
This might be the answer - from JavaScript Comparison Operators (Mozilla documentation):
Equal (==)
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 either operand is a string, the other one is converted to a string
Highly recommended: Douglas Crockford on JavaScript.
Answer: aTruthyValue and true are not the same.
The semantic of the if statement is easy:
if(aTruthyValue) {
doThis
} else {
doThat
}
Now it's just the definition of what a truthy value is. A truthy value is, unfortunately, not something that is simply "== true" or "=== true".
ECMA-262 1.5
Setion 9.2 explains what values are truthy and which are not.
I recommend using === whenever possible, if only to avoid having existential crises.

What is exactly the meaning of "===" in javascript? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Javascript === vs ==
What's the diff between "===" and "==" ? Thanks!
'===' means equality without type coersion. In other words, if using the triple equals, the values must be equal in type as well.
e.g.
0==false // true
0===false // false, because they are of a different type
1=="1" // true, auto type coersion
1==="1" // false, because they are of a different type
Source: http://longgoldenears.blogspot.com/2007/09/triple-equals-in-javascript.html
Ripped from my blog: keithdonegan.com
The Equality Operator (==)
The equality operator (==) checks whether two operands are the same and returns true if they are the same and false if they are different.
The Identity Operator (===)
The identity operator checks whether two operands are “identical”.
These rules determine whether two values are identical:
They have to have the same type.
If number values have the same value they are identical, unless one or both are NaN.
If string values have the same value they are identical, unless the strings differ in length or content.
If both values refer to the same object, array or function they are identical.
If both values are null or undefined they are identical.
The === operator means "is exactly equal to," matching by both value and data type.
The == operator means "is equal to," matching by value only.
It tests exact equality of both value and type.
given the assignment
x = 7
x===7 is true
x==="7" is false
In a nutshell "===" tests for the equality of value AND of type:
From here:

Categories