why do parseInt and isNaN in JavaScript have inconsistent behavior? - javascript

I'm using node.js with v8.11.3.
parseInt("") returns NaN, but isNaN("") returns false:
console.log(
parseInt(''),
isNaN('')
);
another example:
console.log(
parseFloat('0x5'),
parseInt('0x5')
);

Per MDN docs, parseInt:
If the first character cannot be converted to a number, parseInt returns NaN.
There is no first character in the empty string - it cannot be converted to a number, so NaN is returned.
But isNaN is different. As the first paragraph of MDN says:
Note: coercion inside the isNaN function has interesting rules; you may alternatively want to use Number.isNaN(), as defined in ECMAScript 2015.
...
When the argument to the isNaN function is not of type Number, the value is first coerced to a Number.
The empty string, when coerced to a Number, is 0:
const result = Number('');
console.log(result + ' : ' + typeof result);
You might try using parseInt and then checking to see if the result is NaN or not:
const possibleInt = parseInt('');
console.log(Number.isNaN(possibleInt));

The use of Number() just shuffles the problem around. For example:
parseInt("14px"); // 14
parseInt("abc"); // NaN
parseInt(""); // NaN (i.e. null string is a number)
versus use of isNaN:
isNaN("14px"); // false
isNaN("abc"); // true
isNaN(""); // false
versus use of Number():
Number("14px"); // NaN
Number("abc"); // NaN
Number(""); // 0
And, making it more complicated, you can't even do:
parseInt(x) == NaN ? 0 : parseInt(x);
because comparisons with NaN are always false, even NaN == NaN is false.
The simplest that I found was:
x=="" || !isNaN(x) ? 0 : parseInt(x);
but this assumes that the null string is the only anomaly, so it may not work in all cases.

Related

Unary + operator in JavaScript applied to ' ' (string with space) [duplicate]

Today when I was doing some experiments with ==, I accidentally found out that "\n\t\r" == 0. How on earth does "\n\t\r" equal to 0, or false?
What I did is:
var txt = "\n"; //new line
txt == 0; //it gives me true
And that really annoy me. So I did more:
var txt = "\r"; //"return"
txt == 0; //true
var txt = "\t"; //"tab"
txt == 0; //true
It does not make sense, at all. How's that happen? And more crazy is this:
//Checking for variable declared or not
var txt ="\n\t\r";
if(txt!=false){
console.log("Variable is declared.");
}else{
console.log("Variable is not declared.");
}
What it gives me is Variable is not declared.
How is it equal to 0, or false???
This behaviour might be surprising but can be explained by having a look at the specification.
We have to look at the what happens when a comparison with the equals operator is performed. The exact algorithm is defined in section 11.9.3.
I built a simple tool to demonstrate which algorithm steps are executed: https://felix-kling.de/js-loose-comparison/
string == integer
The step we have to look at is #5:
5. If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
That means the string "\n" ("\r", "\t") is converted to a number first and then compared against 0.
How is a string converted to a number? This is explained in section 9.3.1. In short, we have:
The MV (mathematical value) of StringNumericLiteral ::: StrWhiteSpace is 0.
where StrWhiteSpace is defined as
StrWhiteSpace :::
StrWhiteSpaceChar StrWhiteSpace_opt
StrWhiteSpaceChar :::
WhiteSpace
LineTerminator
This just means that the numerical value of strings containing white space characters and/or a line terminator is 0.
Which characters are considered as white space characters is defined in section 7.3.
string == boolean
The step we have to look at is #7:
7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
How booleans are converted to numbers is pretty simple: true becomes 1 and false becomes 0.
Afterwards we are comparing a string against a number, which is explained above.
As others have mentioned, strict comparison (===) can be used to avoid this "problem". Actually you should only be using the normal comparison if you know what you are doing and want this behaviour.
Because JavaScript is a loosely typed language, it attempts to type cast your 1st side of the comparison to the other so that they would match each other.
Any string which does not contain a number, becomes 0 when compared to an integer, and becomes true (Except in certain situations), when compared to a Boolean.
Light reading material.
txt is not a Boolean, so it will never be false. It can be undefined though.
var txt ="\n\t\r";
if(txt !== undefined) { //or just: if (txt)
console.log("Variable is declared.");
} else {
console.log("Variable is not declared.");
}
//=> will log: 'Variable is declared.'
By the way, a declared variable may be undefined (e.g. var txt;).
If you do a stricter comparison (without type coercion, using ===), you'll see that
var txt = '\n'; txt === 0; //=> false
var txt = '\r'; txt === 0; //=> false
var txt = '\t'; txt === 0; //=> false
See also
The reason is that "\n\t\r" just as " " are treated as empty strings.
If you use == it will return true but if you use === it will return false.
If you want to test for existence you should use something like
if(typeof strName !== 'undefined') {
/*do something with strName*/
} else {
/*do something without it*/
}
Whenever you use the == operator and try to compare a string to a number, the string will first be converted to a number. Thus: alert("\n\r"==0) becomes: alert(Number("\n\r")==0)
The Number constructure is kind of interesting. It will first strip whitespace then decide if the number is a not a number or not. If NaN, then the result is "NaN". If the string is empty, then the result is 0.
alert(Number()) alerts 0
alert(Number("")) alerts 0
alert(Number(" \n \r \n \t")) alerts 0
alert(Number("blah")) alerts NaN
alert(Number("0xFF")) alerts 255
alert(Number("1E6")) alerts 1000000
To check if the result is NaN use isNaN()
Thus: alert(isNaN("blah")) alerts true
Thus: alert(isNaN("")) alerts false
Thus: alert(isNaN("\n")) alerts false
Thus: alert(isNaN(" ")) alerts false
however do note that NaN will never equal NaN:
var nan=Number("geh");alert(nan==nan); alerts false
Update:
if you want to check if both sides are NaN, then you'd convert both to boolean values first like so:
var nan=Number("geh");alert(!!nan==!!nan); alerts true
or better yet
var nan=Number("geh");
alert(isNaN(nan)&& isNaN(nan));

Remove NaN value, javascript

Index 28:
How do I remove this "NaN" value. Cant use isNaN because I want strings and numbers. But not NaN
Tried:
typeof value === 'undefined'
value == null
No success.
You can test for NaN specifically by using Number.isNaN, which is subtly different from plain isNaN: It only returns true if its argument is a number (whose value is NaN). In other words, it won't try to coerce strings and other values to numbers.
Demo:
const values = [
12,
NaN,
"hello",
{ foo: "bar" },
NaN,
null,
undefined,
-3.14,
];
const filtered = values.filter(x => !Number.isNaN(x));
console.log(filtered);
Number.isNaN is new in ECMAScript 6. It is supported by every browser except Internet Explorer. In case you need to support IE, here's a simple workaround:
if (!Number.isNaN) {
Number.isNaN = function (x) { return x !== x; };
}
you can use typeof (to check that's a number) in combination with isNaN
Note that typeof NaN returns "number"
typeof x === "number" && isNaN(x)
Another solution is to use Number.isNaN which will not trying to convert the parameter into a number. So it will return true only when the parameter is NaN
You should be able to use Number.isNaN
console.log([1, "foo", NaN, "bar"].filter((x) => !Number.isNaN(x)))
I’ve seen this comparison check, not sure if you could make it work for you.
var nanValue = NaN;
if(nanValue !== nanValue) // Returns true!
alert('nanValue is NaN');

strings and numbers in comparisons in Javascript

var result='16'>'141';
console.log(result);
var result='16'>141;
console.log(result);
That’s because if any of the operands is not string, then both
operands become numbers, and the comparison becomes correct.
Can anyone tell me. How below equation is evaluate?
var result='a'>11;
console.log(result);
'a'>11=> Answer should be true instead of false;
because
'a' will convert to int 97 > 11 => true then how it evaluate false.
If I go like this 'a'>'11' => then it answer comes true.
var result='a'>'11';
console.log(result);
When you convert a non-numeric string like 'a' to a Number, you get NaN:
console.log(+'a'); // NaN
console.log('a' * 1); // NaN
console.log(Number('a')); // NaN
And NaN always produces false in relational comparisons. Trichotomy does not hold:
console.log(NaN < 0); // false
console.log(NaN > 0); // false
console.log(NaN == 0); // false
If you want to convert 'a' to 97, use charCodeAt:
console.log('a'.charCodeAt(0)); // 97
Javscript use The Abstract Equality Comparison Algorithm
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
When comparing a string and a number, string is converted to a number, but you are thinking like some ASCII code.
Since 'a' is not a number so it's comparison with a number will give you false in any case > , < or ==.

why does "[] == 0" return true while "[]" is true and "0" is false?

If i execute the following lines in thw browser console
!![] //--- returns true
!!0 //--- returns false
I get that [] and 0 have different boolean values.
I don't understand why
[] == 0 //--- returns true
returns true.
What am I missing?
Remember that array is object and 0 is number.
And as "user2864740" told..
1) When you doing
!![] //--- returns true
!!0 //--- returns false
You are performing so called "ToBoolean" convertion
https://es5.github.io/#x9.2
Number
The result is false if the argument is +0, −0, or NaN; otherwise the
result is true.
Object ( our [] )
always true
2) But when you using == you performing so called "Equality Comparison"
https://es5.github.io/#x11.9.3
Here thins a little bit complicated but to understand what happens you have to remember that == do a type coercion ( so you can compare oranges to apples :) )
First of all compiler converts [] to some primitive type.
If Type(x) is either String or Number and Type(y) is Object, return
the result of the comparison x == ToPrimitive(y).
How ToPrimitive works is a matter of an article :), but's it easy to remember that closet primitive type to array is string. Array will be converted to empty string.
[].toString() === ""
So now we need to compare empty string and number 0
"" == 0 // true
Hmmm. So it's true. But why is that? Remember that when you compare with "Equality Comparison" number and string
If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
So let's try to convert empty string to number
Number("") === 0
And in the end
0 === 0
I hope that's explains something :)
JavaScript is probably converting the array to a number:
!!Number([]) // false
Number([]) == 0 // true

Proper way to convert number to string in javascript

According to tutorial by w3schools (http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_tostring_number), we can use toString() method on a integer var. Kindly look at the following code:
var num = 15;
var n = num.toString();
alert(isNaN(n));
If toString() method is working, why isNaN(n) returning false?
The IsNaN method tries converting the string passed to it back to a number, and since "15" is still actually a number, the method returns false.
See: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/isNaN
isNaN() coerces the string '15' into a number value before checking it.
isNaN even coerces booleans, and some falsy values into numbers.
isNaN(true) // >> false
isNaN(false) // >> false
isNaN([]) // >> false
isNaN('') // >> false
Try using typeof to figure out if it's a number or not
var num = 15;
var n = num.toString();
alert(typeof n === 'number');
isNaN() function returns true if the value is NaN, and false if not.
Your code is excute alert(isNaN(15));
So it is return false

Categories

Resources