How to inconsistency between parseFloat("") and isNaN("") - javascript

I need to check if value isNaN("") === true but it returns false but parseFloat("") returns NaN.
Why I need this is because I am doing hash check with JSON.stringify() and knockout observable instead of numeric value returns a string numeric value.
E.g. Instead of 1.23 it returns "1.23".
Question: How to parse string numeric values without getting NaN as result?

How to parse string numeric values without getting NaN as result?
Well...you can't, if the values can't be parsed as numeric values. But "1.23" can be parsed as a numeric value:
var num = parseFloat("1.23");
console.log(num); // 1.23
If you need to check if the result will be NaN, check the result:
isNaN(parseFloat(yourInput)) === true
...except there is exactly zero point in the === true part of that, so:
isNaN(parseFloat(yourInput))
parseFloat and the default coercion to number used if you pass a string into isNaN follow different rules. In particular, parseFloat will stop parsing as of the first non-numeric, but isNaN [in effect] uses the Number function, which will fail if there are non-numeric characters. So if you need to rely on getting a result from parseFloat that is not NaN, you have to call parseFloat and pass its result into isNaN.
Here's an example: "1.23aaa" Let's see what we see there:
console.log(parseFloat("1.23aaa")); // 1.23
console.log(isNaN("1.23aaa")); // true!!
console.log(isNaN(parseFloat("1.23aaa"))); // false
parseFloat stops trying as of the first a, but the default coercion from string to number you're invoking by passing a string into isNaN doesn't.

Related

why parseInt() in javascript converting "1abc" to 1?

I am trying to understand how parseInt() will work in javascript, my scenarios are
var x = parseInt("123");
console.log(x); // outputs 123
var x = parseInt("1abc");
console.log(x); // outputs 1
var x = parseInt("abc");
console.log(x); // outputs NaN
as of my observation parseInt() converts a string to integer(not really an integer of string like "12sv") when the string begins with number.
but in reality it should return NaN.
From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
"If the first character cannot be converted to a number, parseInt returns NaN."
From Mozilla's docs: "If parseInt encounters a character that is not a numeral in the specified radix, it ignores it and all succeeding characters and returns the integer value parsed up to that point."
So it will parse up to the first invalid character, drop the rest of the string, and return the int it managed to parse until then. If there's no valid characters it will return NaN.
parseInt()->it simply parse the provided value to its equivalent radix conversion,if specified without radix it converts to decimal equivalent.
for coercion purpose, we should avoid using parseInt,we can use Number() function instead.

Why does parseInt fail to test Arrays properly in Javascript?

Given:
var obj={0:21,1:22}
and
var arr=[21,22]
Why does parseInt(obj) return NaN, but parseInt(arr) returns 21?
I had a function where I was either going to pass an int, a hash type object or a plain array. I was expecting parseInt to return NaN for both object and array, thus simplifying argument checking. What gives?
This is because parseInt tries to coerce the first argument to a string before parsing to an integer. String(obj) returns "[object Object]" and can't be parsed, but String([21,23]) returns "21,23", which parseInt parses until it reaches the unparseable char.
See the parseInt spec:
Let inputString be ? ToString(string).
(Coerce the input to a string).
If S contains a code unit that is not a radix-R digit, let Z be the substring of S consisting of all code units before the first such code unit; otherwise, let Z be S.
(Drop any part of the string starting with non-digit character, so "21,23" -> "21").

Type conversion of Boolean to Number in JavaScript

I was working on type conversion of Boolean values to Number in javascript.
console.log(new Number(true));//Prints 1
console.log(+true);//Prints 1
console.log(parseInt(true));//Prints NaN
Why is the parseInt is throwing NaN? While first and second case given above are working fine.
Because parseInt expects a string and 'true' is NaN.
From MDN:
parseInt()
The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).
If you are actually working on number conversions then this table might be very helpful:
Number constructor invokes toNumber internally which as per spec
Boolean - Return 1 if argument is true. Return +0 if argument is
false.
Which means Number(true) returns 1.
However, parseInt invokes toString internally and as per spec
Boolean
If argument is true, return "true".
If argument is false, return "false".
Which means parseInt(true) -> parseInt("true") -> NaN
since as per spec again
If number is NaN, +0, −0, +∞, or −∞, return +0.
Hope this helped.

Why is an Array with one Number a Number in Javascript?

I've found that an empty array or an arwith exactly one Number is a Number.
This topic is not really an explanation for this special case I think: Why does isNaN(" ") equal false
document.write( isNaN([1,2,3]) ); // true
document.write( isNaN([1,2,'abc']) ); // true
document.write( isNaN(['abc']) ); // true
// maybe explained through the above link
document.write( isNaN([]) ); // false
// but...
document.write( isNaN([1]) ); // false
document.write( isNaN([-3]) ); // false
document.write( isNaN([1234567]) ); // false
document.write( isNaN([-1.234]) ); // false
document.write( isNaN([[123]]) ); // false
document.write( isNaN(['1']) ); // false
Who can tell me why it makes sense?
isNaN coerces its value to a number. (See MDN)
Because the string representation of an array is all of its items concatenated with a comma. And the numerical representation of that is NaN because of the comma.
But if there's only one item, hence no comma, it's able to be converted to a number.
You're using the isNaN global function which has some confusing behavior due to its coercion of non-numbers to a numeric type which can then result in the NaN value. This is what is happening in your case as the string representation of an array containing a single number element will successfully parse to the number value of the single number element.
From MDN:
Since the very earliest versions of the isNaN function specification, its behavior for non-numeric arguments has been confusing. When the argument to the isNaN function is not of type Number, the value is first coerced to a Number. The resulting value is then tested to determine whether it is NaN. Thus for non-numbers that when coerced to numeric type result in a valid non-NaN numeric value (notably the empty string and boolean primitives, which when coerced give numeric values zero or one), the "false" returned value may be unexpected; the empty string, for example, is surely "not a number."
Note also that with ECMAScript 6, there is also now the Number.isNaN method, which according to MDN:
In comparison to the global isNaN() function, Number.isNaN() doesn't suffer the problem of forcefully converting the parameter to a number. This means it is now safe to pass values that would normally convert to NaN, but aren't actually the same value as NaN. This also means that only values of the type number, that are also NaN, return true.
Unfortunately:
Even the ECMAScript 6 Number.isNaN method has its own issues, as outlined in the blog post - Fixing the ugly JavaScript and ES6 NaN problem.

How the string.charAt() works when passing in a string as argument?

According to the MDN JS Doc, the charAt method takes in an integer and returns an the character at the index. And
If the index you supply is out of range, JavaScript returns an empty string.
What I found is that it also takes string as an argument and the return value is intriguing.
The example code: http://jsfiddle.net/yangchenyun/4m3ZW/
var s = 'hey, have fun here.'
>>undefined
s.charAt(2);
>>"y" //works correct
s.charAt('2');
>>"y" //This works too
s.charAt('a');
>>"h" //This is intriguing
Does anyone have a clue how this happens?
The algorithm is described in Section 15.5.4.4 in the specification. There you will see (pos being the parameter passed to charAt):
(...)
3. Let position be ToInteger(pos).
(...)
ToInteger is described in Section 9.4:
Let number be the result of calling ToNumber on the input argument.
If number is NaN, return +0.
(...)
'a' is not a numerical string and hence cannot be converted to a number, so ToNumber will return NaN (see Section 9.3.1) which then results in 0.
On the other side, if you pass a valid numerical string, such as '2', ToNumber will convert it to the corresponding number, 2.
Bottom line:
s.charAt('a') is the same as s.charAt(0), because 'a' cannot be converted to an integer.

Categories