I got these 2 examples below -
console.log("a" > "3") // outputs true
console.log("hello" > "3") // outputs true
According to MDN, If both values are strings, they are compared as strings, based on the values of the Unicode code points they contain.
But then they also wrote the following in the next paragraph, Strings are converted based on the values they contain, and are converted as NaN if they do not contain numeric values.
Following this logic, shouldn't both statements be false since no matter what the operator it is, "a" and "hello" are words in strings and they don't have a numerical value, therefore, it should return NaN, and NaN is false; hence, as soon as one of the operands is false, it outputs false?
If I need to adhere to the former statement above, could you please walk me through this logic?
Thanks.
The key phrase from the MDN article is
If both values are strings, […].
Otherwise JavaScript attempts to convert non-numeric types to numeric values
So no, "a", "3" and "hello" are all strings, and when comparing them, they get compared as strings. No conversion to anything occurs.
You are comparing two strings (in quotation marks), not a string to a number. This should answer your question:
"a" > "3" //true
"a" > 3 //false
As you've written,
If both values are strings, they are compared as strings, based on the
values of the Unicode code points they contain
So, on both examples, both values are strings. If you change "3" to 3, the result is:
console.log("a" > 3)
// expected output: false
console.log("hello" > 3)
// expected output: false
That's because, first it's converted as NaN, and then:
If either value is NaN, the operator returns false.
The docs:
If both values are strings, they are compared as strings, based on the values of the Unicode code points they contain.
Otherwise JavaScript attempts to convert non-numeric types to numeric values: ....
Reading the docs, I understand that, if BOTH strings have numerical values (both not NaN), then both are treated as Unicode code points. Otherwise, if BOTH have numerical values, then they're converted.
But anyways, my sugestion for a js beginer: do not get too attached to how the language works for now, and even tho it can compare strings with "greater" and "less than", I dont think there would (or should) be a real life scenario where you would need it.
Also, just for fun, check this pen I made when I first started with js (I was also very confused about comparison and typing xD):
"" == null // this one is fun
Later, after learning more about the language, you'll get why somethings work like they do in js, I also recomending understanding the history of js and the web, it explains a lot of the weird behaviours of the language.
Related
When working in the console of developer tools in chrome, I types in,
2 + []
and it produced the unexpected result "2". The same happens with every number. What is happening? Also, when we add some number to a nonempty array, it concatenates the number and the first element of that list, e.g., 2+["abc",6] produces "2abc, 6".
Note: I don't have much experience in js.
This is due to coercion in javascript.
both 2 and [] are tried to get converted to a common type - string.
Now, toString method of array returns "" and toString of Number returns "2" in this case.
Therefore to get the result - "2" after "" and "2" are concatenated.
From What I observe, Javascript does implicit type conversions and if both sides of the operand are different, JS will try to typecast them to string in case of + operation.
For example, if you try [12,34].toString() it will return "12,34" and and if you do 2+[] js will interpret it as 2.toString() + [].toString() thus the output "2".
You can try different combinations in your browser console for more experiments.
I'm implementing a sort function and came across the following:
'49' > '5' // false
'49' > '4' // true
new String(49).localeCompare('4') // 1
new String(49).localeCompare('5') // -1
Expected behaviour is obviously that 49 > 4 or 5 should be true. Is there any way to solve this without converting the strings to numbers?
That is actually expected behavior when comparing strings, as described here. The easiest thing for this situation would be to convert the values to numbers for comparison if you want to compare them as numbers.
Thinking outside the box a little, you could first compare the length of the strings before using the > operator. If they are numeric strings, the longer string would have a higher value (assuming you don't have numbers like '0024'). If they are equal in length, the > operator would then work as you expect.
In JavaScript, variables are loosely typed, so the number 5 and the string "5" may both be treated as a number by several operators. However, is there a generic way to find out JavaScripts conversion abilites in at tunrime, or is it just the overloading of operators for several types that make the loose typing possible?
For example, given a variable a and a string containing a type name type_canditate, is there any way to ask JavaScript, if a may convert to type_candidate in a feasable manner, in contrast to the hard typing operators like instanceof? For example, "5" instanceof Number evaluates false, while Math.sin("5") is perfectly feasable. For numbers, one can obviuosly check if parseFloat(some_number) evaluates to NaN, but this is a special case for numbers.
So, is there any generic way of naming types, and check if some variable may convert to a given type in a useful manner?
There are three primitive data types in JavaScript: string, number and boolean.
Anything can be converted to a string or boolean:
All objects convert to true (except null, which becomes false - I only mention it here because typeof null gives object)
All objects have a built-in toString method which is called when converting to a string.
Converting a number to a string is done by giving the string representation of the number (ie. 5 becomes "5")
Numbers convert to boolean true, unless it's 0 which becomes false.
Converting to a number is a little trickier, but technically possible. If it can find a valid number, then it becomes that number. Otherwise, it becomes NaN.
So basically... any type can become any other type through casting in this way. The only time you have anything resembling an "error condition" is NaN.
Boot up your interpreter/console and try the comparison
> ",,," == Array(4)
True
Why? At first I thought maybe since you could think of ",,," as an array of four characters with a '\0' terminating slice, that might be why, but
> "..." == Array(4)
Returns "False". So... why? I know it's some idiosyncratic bit of duck typing in Javascript, but just curious what underlines this behavior. Gleaned this from Zed Shaw's excellent presentation here btw.
Because the right hand operand is converted to a string and the string representation of Array(4) is ,,,:
> Array(4).toString()
",,,"
If you use the array constructor function and pass a number, it sets the length of the array to that number. So you can say you have four empty indexes (same as [,,,]) and the default string representation of arrays is a comma-separated list of its elements:
> ['a','b','c'].toString()
"a,b,c"
How the comparison works is described in section 11.9.3 of the specification. There you will see (x == y):
8. If Type(x) is either String or Number and Type(y) is Object,
return the result of the comparison x == ToPrimitive(y).
(arrays are objects in JavaScript)
and if you follow the ToPrimitive method you will eventually find that it it calls toString.
Internally its going
",,," == Array(4).toString()
Try using ===. When using == in Javascript, it will attempt to cast the variables, thus leading to issues like this one. The console is casting Array(4) to the string representation (i.e. Array(4).toString), which is ",,,". The reason the commas are there is that the .toString() function adds them to separate items in an array.
See the snippet below:
document.write( Array(4).toString() );
This is because Array(4) initialises an array of 4 empty values, an == implicitly converts, so:
",,," == Array(4)
",,," == Array(4).toString()
",,," == ["", "", "", ""] // note 3 commas for 4 values
",,," == ["", "", "", ""].toString()
Are all similar.
== does implicit type conversions before comparing the values, which can result in unpredictable results. Use === to check the type and the value.
Comparing an Array to a string coerces the Array to a string before doing the comparison. Coercing an empty 4-element Array to a string yields that exact string.
I first thought it was something with the "prototype"... but after a little investigation I reached a sad conclusion...
Apparently it is an internal and more obscure js thing with not much logic...
Just try
Array(4)==Array(4)
and no coercion on types also...
Array(4)===Array(4)
and you'll get FALSE
you know that null==null, null===null and even undefined==undefined and undefined===undefined returns TRUE... so... it's a bit obscure...
Array(4)==[,,,] should be true also
I understand that using the "===" compares type, so running the following code results in "not equal" because it's comparing a number type to a string type.
var a = 20;
var b = "20";
if (a === b) {
alert("They are equal");
} else {
alert("They are not equal");
}
But I dont understand how using the "==" to compare only the value results in the "They are equal" message.
var a = 20;
var b = "20";
if (a == b) {
alert("They are equal");
} else {
alert("They are not equal");
}
How are the values equal? Isn't the string "20" stored as the ASCII characters 50 and 48 (0110010 and 0110000 in binary) and 20 stored as the actual binary number 0010100?
EDIT: Thanks everyone! I think all the responses are great and have helped me understand this much better.
The == operator compares only the values of the variables. If the types are different, a conversion is operated. So the number 20 is converted to the string "20" and the result is compared.
The === operator compares not only the values, but also the types, so no cast is operated. In this case "20" !== 20
The JavaScript engine sees the a as a number and casts the b to number before the valuation.
When type conversion is needed, JavaScript converts String, Number, Boolean, or Object operands as follows.
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.
If one of the operands is Boolean, the Boolean operand is converted to 1 if it is true and +0 if it is false.
If an object is compared with a number or string, JavaScript attempts to return the default value for the object. Operators attempt to convert the object to a primitive value, a String or Number value, using the valueOf and toString methods of the objects. If this attempt to convert the object fails, a runtime error is generated.
The problem with the == comparison is that JavaScript version 1.2 doesn't perform type conversion, whereas versions 1.1 and 1.3 onwards do.
The === comparison has been available since version 1.3, and is the best way to check of two variables match.
If you need your code to be compatible with version 1.1, 1.2 and 1.3 versions of JavaScript code, you should ensure that the variables all match as if it was an === comparison that was being performed.
Part of the definition of "==" is that the values will be converted to the same types before comparison, when possible. This is true of many loosely typed languages.
Javascript is designed such that a string containing numbers is considered "equal" to that number. The reason for that is simplicity of use for the case of users entering a number into an input field and the site validates it in JS -- you don't have to cast the entered string to a number before comparing.
It simplifies a common use case, and the === operator still allows you to compare with the type considered as well.
As far as I know JavaScript does automatic data type conversion on the fly - so maybe the variables are casted to equivalent types automatically.