What is the logic of comparing int with string and array? [duplicate] - javascript

This question already has answers here:
Why is "0" == [] false? [duplicate]
(4 answers)
Empty arrays seem to equal true and false at the same time
(10 answers)
Closed 4 years ago.
I were trying to play around the equal to == operator in Javascript, and I got the following results:
0 == "0" // true
and also
0 == [0] // true
HOWEVER:
"0" == [] // false
Honestly, this is kind of confusing for me since I have no Javascript-background.
Also, I noticed that:
"0" == [0] // true
and that is also applicable for other values:
1 == [1] // true
1 == "1" // true
"1" == [1] // true
101 == "101" // true
101 == [101] // true
"101" == [101] // true
So it seems to be about comparing 0 with an empty array [].
What is logic behind it?

If you see the Loose equality using == chart on Mozila Developer Network here at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness you can see that
If Operand A is string in your case "0" and Operand B is Object in your case [] then Operand B will be converted to primitive type like new String([]) returns ""
A == ToPrimitive(B)
Then if we try,
> typeof "0"
"string"
> typeof []
"object"
> "0"=="" // it will return false
If you try with
> 0==[] // it will return true

It happens because of type coercion (using double =). Basically when comparing variables that are not of equal types, javascript tries and covert them to the same type and the compare them. To avoid this use triple equals (===) when comparing variables.
To know more about javascript I recommend these books (free online!)
https://github.com/getify/You-Dont-Know-JS
but if you're interested in this topic specifically you can read this one:
https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch4.md
PS. Down at the end is exactly your example explained in detail.
Good luck!

It is working based Abstract equality comparison algorithm. Let me pick a single example from yours and explain how it is returning the results,
0 == [0]
So the main aim of AECA is to bring the lhs and rhs to a same type. Based on the algorithm, internally recursive steps would happen to make both the sides of same type.
i] 0 == [0]
ii] 0 == toPrimitive([0])
iii] 0 == '0'
iv] 0 == toNumber('0')
v] 0 == 0
vi] true

To put it simply, javascript will try most of the times to convert the sides of the equality to numbers if they are of different type.
For object, it will however call the abstract operation toPrimitive (with a hint of default). That operation calls .valueOf and then .toString on the result if it's still not a primitive ( meaning something else than an object).
0 == "0" => 0 == 0 => true
0 == [0] => 0 == "0" ( .valueOf returns [0] so .toString is used)
"0" == [] => "0" == "" => false ( they have the same type so the string must be the same to be true)
0 == [] => 0 == "" => 0 == 0 : true
The full resource is here:
https://www.ecma-international.org/ecma-262/8.0/#sec-abstract-equality-comparison

Related

Why is null < 1 true in JavaScript? [duplicate]

I had to write a routine that increments the value of a variable by 1 if its type is number and assigns 0 to the variable if not, where the variable is initially null or undefined.
The first implementation was v >= 0 ? v += 1 : v = 0 because I thought anything not a number would make an arithmetic expression false, but it was wrong since null >= 0 is evaluated to true. Then I learned null behaves like 0 and the following expressions are all evaluated to true.
null >= 0 && null <= 0
!(null < 0 || null > 0)
null + 1 === 1
1 / null === Infinity
Math.pow(42, null) === 1
Of course, null is not 0. null == 0 is evaluated to false. This makes the seemingly tautological expression (v >= 0 && v <= 0) === (v == 0) false.
Why is null like 0, although it is not actually 0?
Your real question seem to be:
Why:
null >= 0; // true
But:
null == 0; // false
What really happens is that the Greater-than-or-equal Operator (>=), performs type coercion (ToPrimitive), with a hint type of Number, actually all the relational operators have this behavior.
null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined:
null == null; // true
null == undefined; // true
Value such as false, '', '0', and [] are subject to numeric type coercion, all of them coerce to zero.
You can see the inner details of this process in the The Abstract Equality Comparison Algorithm and The Abstract Relational Comparison Algorithm.
In Summary:
Relational Comparison: if both values are not type String, ToNumber is called on both. This is the same as adding a + in front, which for null coerces to 0.
Equality Comparison: only calls ToNumber on Strings, Numbers, and Booleans.
I'd like to extend the question to further improve visibility of the problem:
null >= 0; //true
null <= 0; //true
null == 0; //false
null > 0; //false
null < 0; //false
It just makes no sense. Like human languages, these things need be learned by heart.
JavaScript has both strict and type–converting comparisons
null >= 0; is true
but
(null==0)||(null>0) is false
null <= 0; is true but (null==0)||(null<0) is false
"" >= 0 is also true
For relational abstract comparisons (<= , >=), the operands are first converted to primitives, then to the same type, before comparison.
typeof null returns "object"
When type is object javascript tries to stringify the object (i.e null)
the following steps are taken (ECMAScript 2015):
If PreferredType was not passed, let hint be "default".
Else if PreferredType is hint String, let hint be "string".
Else PreferredType is hint Number, let hint be "number".
Let exoticToPrim be GetMethod(input, ##toPrimitive).
ReturnIfAbrupt(exoticToPrim).
If exoticToPrim is not undefined, then
a) Let result be Call(exoticToPrim, input, «hint»).
b) ReturnIfAbrupt(result).
c) If Type(result) is not Object, return result.
d) Throw a TypeError exception.
If hint is "default", let hint be "number".
Return OrdinaryToPrimitive(input,hint).
The allowed values for hint are "default", "number", and "string". Date objects, are unique among built-in ECMAScript object in that they treat "default" as being equivalent to "string".
All other built-in ECMAScript objects treat "default" as being equivalent to "number". (ECMAScript 20.3.4.45)
So I think null converts to 0.
console.log( null > 0 ); // (1) false
console.log( null == 0 ); // (2) false
console.log( null >= 0 ); // (3) true
Mathematically, that’s strange. The last result states that "null is greater than or equal to zero", so in one of the comparisons above it must be true, but they are both false.
The reason is that an equality check == and comparisons > < >= <= work differently. Comparisons convert null to a number, treating it as 0. That’s why (3) null >= 0 is true and (1) null > 0 is false.
On the other hand, the equality check == for undefined and null is defined such that, without any conversions, they equal each other and don’t equal anything else. That’s why (2) null == 0 is false.
I had the same problem !!.
Currently my only solution is to separate.
var a = null;
var b = undefined;
if (a===0||a>0){ } //return false !work!
if (b===0||b>0){ } //return false !work!
//but
if (a>=0){ } //return true !
It looks like the way to check x >= 0 is !(x < 0) In that way make sense the response.

Why is [0] === [0] false

If debugging shows that a variable is 0, then I think that I should be able to catch it with either ==='0' or ===0 but that didn't work. I had to use only == instead, then it worked:
var offset = 0;
alert("## DEBUG non_sortable_columns " + non_sortable_columns)
if (non_sortable_columns == '0' || non_sortable_columns == 0) {
offset = 1;
}
I first tried this but it didn't work:
var offset = 0;
alert("## DEBUG non_sortable_columns " + non_sortable_columns)
if (non_sortable_columns === '0' || non_sortable_columns === 0) {
offset = 1;
}
The value was [0] and [0] === [0] is false. How can it be false?
1. [0] === [0] is false because each [0] is actually a declaration that creates an array with the number 0 as its first index. Arrays are objects and in JavaScript, 2 objects are == or === only and only if they point at the same location in memory. This means:
var a = [];
var b = a;
console.log(a == b); // "true". They both point at the same location in memory.
a = [];
b = [];
console.log(a == b); // "false". They don't point at the same location in memory.
2. [0] == "0" evaluates to true, because: In JavaScript, due to the nature of the == operator, when you compare an object with a primitive, the object will be coerced to a primitive, and then that primitive will be coerced to the specific type of primitive you are trying to compare it with.
"0" is a string, so [0] will have to be coerced to a string. How ? First, JavaScript will invoke its valueOf method to see if it returns a primitive, the array version of valueOf will just return that array, so valueOf doesn't yield a primitive; now JavaScript will try the object's (aka array's) toString method, an array's toString method will return a string that is the result of a comma-separated concatenation of its elements (each element will be coerced to a string as well, but that is irrelevant here), this would have been more visible if your array contained more than one element (e.g if it were [0,1], toString would return "0,1"), but your array only has 1 element, so the result of its stringification is "0" (if toString didn't return a string but another primitive, that primitive would be used in a ToString abstract operation; if neither valueOf nor toString returned a primitive, a TypeError would be thrown).
Now, our end comparison, with all the coercions and stuff, has changed to "0" == "0", which is true.
3. [0] == 0, mostly the same as #2, except after JavaScript has the string "0", it will coerce it to a number, the result of coercing the string "0" to a number is the number 0. So we have 0 == 0 which is true.
4. [0] === 0 and [0] === "0", these 2 are very simple, no coercions will happen because you are using ===.
In the first one, the reference (aka location pointed at in memory) held by [0] will be compared to the number 0, this will obviously evaluate to false;
In the second one, again, the reference held by [0] will be compared with the string "0", this again, is false.
So, as you can see, good ser, all your misery comes from ==, this operator, along with !=, are called "the evil counterparts of === and !==" by Douglas Crockford, for the same reasons which are causing your confusions.
Feel free to request any elaborations you might want and ask any questions you might have.
Additionally, see this article about object coercion, this MDN article about Array#toString, and this StackOverflow question which outlines the differences between == and ===.
I just did the following test
var num = 0;
console.log("Number: ", num);
if(num === '0' || num === 0) {
console.log("Num is 0 (===)");
}
if(num == '0' || num == 0) {
console.log("Num is 0 (==)");
}
and got the output
Number: 0
Num is 0 (===)
Num is 0 (==)
Try console.log the value itself, if you alert or append strings to a number in JS it will always output as a string. This can be misleading when trying to debug code.
The value of non_sortable_columns might be false.
The basic difference between the === and == is that the 3 equals to comparison operator also checks the type of the variable, that means: '0' which is a string would not be equal to: 0 which is a number.
In your case the variable non_sortable_columns value might be false which means 0in JavaScript therefore the value of the == finds it same as it doesn't check the type but === fails as it checks the type of it.
For better understanding refer to: Which equals operator (== vs ===) should be used in JavaScript comparisons?

equality in javascript [duplicate]

This question already has answers here:
Which equals operator (== vs ===) should be used in JavaScript comparisons?
(48 answers)
Closed 6 years ago.
When working within javascript can someone provide me a good reference or explanation over testing for equality/inequality and type coercion?
From what I have been reading I see where there are two principles of thought on using eqeq (==) vs. eqeqeq (===) some feel that you should not use eqeq and always as use eqeqeq as it is safer to use.
I have been playing around with some basic samples and I am having trouble discerning the difference or when best to use one over the other:
For example: here is some basic script I was writing out. When I test using eqeq or eqeqeq I get the same result. I have not seen an example yet where I would get a different results (ie. using eqeq returns true where eqeqeq returns false).
function write(message){
document.getElementById('message').innerHTML += message +'<br/>';
}
var tim = { name: "tim" };
var tim2 = { name: "tim" };
//objects are equal to themselves ( == vs ==== eqeq or eqeqeq)
write("tim eq tim: " + (tim == tim)); //returns true
//objects are only equal to themselves regardless of containing value got that
write("tim eq tim2: " + (tim === tim2)); //returns false
//access the primative type to test true or false
write("tim value eq tim2 value: " + (tim.name === tim2.name)); //returns true
//how does this differ in efficency over the eqeq operator? is one safer to use over the other?
//write("tim value eq tim2 value: " + (tim.name == tim2.name)); //also returns true
//testing primatives
write("apple eqeqeq apple: " + ("apple" === "apple")); //true
write("apple eqeqeq apple: " + ("apple" == "apple")); //true
Can someone provide an explanation or reference I can read that helps clarify this a bit more.
cheers,
The difference between == and === is fairly simple: == is a comparison of value. === is a comparison of value and type. Using === will prevent JavaScript from dynamically determining type and compares values exactly as they are.
5 == "5" //true - JS compares the number 5 to a string of "5" and determines the contents are the same
5 === "5" //false - A character is not a number, they can't be the same.
0 == false //true - false is a bool, 0 is numerical, but JS determines that 0 evaluates to false
0 === false //false - numeric is not boolean, they can't be exactly the same thing
5 == 5.0 //true - need I say more?
5 === 5.0 //true - one is a float and one is an int, but JS treats them all as numerical
I find it's critical for tests with functions that can return both false (for failure) and 0 (as a legitimate result).
JS has a total of 5 primitive types = numerical, string, boolean, null and undefined. === requires both arguments to be of the same type and equal value to return true. There are no float, int, long, short, etc - any type of number is lumped together as numerical.
It is simple.
== performs a type conversion and then compares converted values to your desired value
=== doesnt perform type conversion and directly compares your values.
Obviously === is better in terms of performance and accuracy but == is also convinient in some cases so you can use them both if they suit your needs.
comparisons
Cheers!
Below is a very complete list of things that you won't expect when using equality operators
All of the following are true:
0 == ""
0 == " "
0 == []
false == ""
false == " "
false == []
[] == ""
null == undefined
"str" == ["str"]
"1" == true
"0" == false
"null" != null
"false" != false
"true" != true
"undefined" != undefined
"NaN" != NaN
NaN != NaN //exception: NO exception
{} != {} //exception: same reference
[] != [] //exception: same reference
--------------------------------------
new Number(10) !== 10
new String("str") !== "str"
NaN !== NaN //exception: NO exception
{} !== {} //exception: same reference
[] !== [] //exception: same reference
(Some of them came from this source)
In conclusion, never use ==. Not even when you want to:
"It is highly recommended to only use the strict equality operator. In
cases where types need to be coerced, it should be done explicitly and
not left to the language's complicated coercion rules."
(source)
=== is the strict equality operator which returns true only if the variables have the same type and value.
a = 1;
b = "1";
a == b will return true, a === b will return false
The rule of == is not easy to remember, can you get all the right answer of below examples?
"" == "0" // false
0 == "" // true
0 == "0" // true
false == "false" // false
false == "0" // true
false == undefined // false
false == null // false
null == undefined // true
" \t\r\n" == 0 // true
So it is better only use ===, and never use ==.
You must have heard someone that javascript is very loosely typed language.
So as surreal said above
The (==) operator is used when you only want to compare the values of the arguments and do not care about their type
like 5=="5" will return true. This is the case when you want to see (for instance what key the user pressed and you don't care about the the type of it may be a string, a char or an integer).
But there me be a case when the type of arguments also matters. In such cases you want to compare the types of the operators. So in those cases you use the triple equality operator.
For example if you are performing some addition or multiplication operations then you want to make sure that the operands are of the compatible type. So you use the triple (===) operator.

what is the "===", and whats the big difference between it and the "==" [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Javascript === vs == : Does it matter which “equal” operator I use?
whats does the === mean when working with jquery/javascript? and whats the difference between === and ==?
like i got this code
if ($this.val() != '' || ignore_empty === true) {
var result = validateForm($this);
if (result != 'skip') {
if (validateForm($this)) {
$input_container.removeClass('error').addClass('success');
}
else {
$input_container.removeClass('success').addClass('error');
}
}
}
and there is the ===
i just want to understand what it does and whats the difference.
thanks
Both are equals operators. but === is type safe.
== This is the equal operator and returns a boolean true if both the
operands are equal.
=== This is the strict equal operator and only returns a Boolean true
if both the operands are equal and of the SAME TYPE.
for example:
3 == "3" (int == string) results in true
3 === "3" (int === string) results in false
hope this helps
== converts data to one type before comparing, === returns false if data of different types. === is preferrable.
Loosely speaking, it provides stricter comparison.
"0" == 0 // true
"0" === 0 // false
For example...
For further info, I recommend following the link Magnus provided.

Why `null >= 0 && null <= 0` but not `null == 0`?

I had to write a routine that increments the value of a variable by 1 if its type is number and assigns 0 to the variable if not, where the variable is initially null or undefined.
The first implementation was v >= 0 ? v += 1 : v = 0 because I thought anything not a number would make an arithmetic expression false, but it was wrong since null >= 0 is evaluated to true. Then I learned null behaves like 0 and the following expressions are all evaluated to true.
null >= 0 && null <= 0
!(null < 0 || null > 0)
null + 1 === 1
1 / null === Infinity
Math.pow(42, null) === 1
Of course, null is not 0. null == 0 is evaluated to false. This makes the seemingly tautological expression (v >= 0 && v <= 0) === (v == 0) false.
Why is null like 0, although it is not actually 0?
Your real question seem to be:
Why:
null >= 0; // true
But:
null == 0; // false
What really happens is that the Greater-than-or-equal Operator (>=), performs type coercion (ToPrimitive), with a hint type of Number, actually all the relational operators have this behavior.
null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined:
null == null; // true
null == undefined; // true
Value such as false, '', '0', and [] are subject to numeric type coercion, all of them coerce to zero.
You can see the inner details of this process in the The Abstract Equality Comparison Algorithm and The Abstract Relational Comparison Algorithm.
In Summary:
Relational Comparison: if both values are not type String, ToNumber is called on both. This is the same as adding a + in front, which for null coerces to 0.
Equality Comparison: only calls ToNumber on Strings, Numbers, and Booleans.
I'd like to extend the question to further improve visibility of the problem:
null >= 0; //true
null <= 0; //true
null == 0; //false
null > 0; //false
null < 0; //false
It just makes no sense. Like human languages, these things need be learned by heart.
JavaScript has both strict and type–converting comparisons
null >= 0; is true
but
(null==0)||(null>0) is false
null <= 0; is true but (null==0)||(null<0) is false
"" >= 0 is also true
For relational abstract comparisons (<= , >=), the operands are first converted to primitives, then to the same type, before comparison.
typeof null returns "object"
When type is object javascript tries to stringify the object (i.e null)
the following steps are taken (ECMAScript 2015):
If PreferredType was not passed, let hint be "default".
Else if PreferredType is hint String, let hint be "string".
Else PreferredType is hint Number, let hint be "number".
Let exoticToPrim be GetMethod(input, ##toPrimitive).
ReturnIfAbrupt(exoticToPrim).
If exoticToPrim is not undefined, then
a) Let result be Call(exoticToPrim, input, «hint»).
b) ReturnIfAbrupt(result).
c) If Type(result) is not Object, return result.
d) Throw a TypeError exception.
If hint is "default", let hint be "number".
Return OrdinaryToPrimitive(input,hint).
The allowed values for hint are "default", "number", and "string". Date objects, are unique among built-in ECMAScript object in that they treat "default" as being equivalent to "string".
All other built-in ECMAScript objects treat "default" as being equivalent to "number". (ECMAScript 20.3.4.45)
So I think null converts to 0.
console.log( null > 0 ); // (1) false
console.log( null == 0 ); // (2) false
console.log( null >= 0 ); // (3) true
Mathematically, that’s strange. The last result states that "null is greater than or equal to zero", so in one of the comparisons above it must be true, but they are both false.
The reason is that an equality check == and comparisons > < >= <= work differently. Comparisons convert null to a number, treating it as 0. That’s why (3) null >= 0 is true and (1) null > 0 is false.
On the other hand, the equality check == for undefined and null is defined such that, without any conversions, they equal each other and don’t equal anything else. That’s why (2) null == 0 is false.
I had the same problem !!.
Currently my only solution is to separate.
var a = null;
var b = undefined;
if (a===0||a>0){ } //return false !work!
if (b===0||b>0){ } //return false !work!
//but
if (a>=0){ } //return true !
It looks like the way to check x >= 0 is !(x < 0) In that way make sense the response.

Categories

Resources