What's the difference between lodash toNumber and parseInt? - javascript

I know Lodash often adds some extra checks or niceties to functions that already exist in JavaScript but it's not clear what _.toNumber specifically does that I wouldn't get with parseInt.
I'd prefer to use Lodash only when it provides benefits that aren't there with existing JavaScript functions but I can't see any in this case.

I think it is much better to simply look at the _.toNumber source and that would practically answer your question:
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value);
}
As you can see it does a bunch of other things in comparison to parseInt. To be more specific:
console.log(_.toNumber(1), parseInt(1)) // same
console.log(_.toNumber('1'), parseInt('1')) // same
console.log(_.toNumber('b'), parseInt('b')) // same
console.log(_.toNumber({}), parseInt({})) // same
console.log(_.toNumber(' 1 '), parseInt(' 1 ')) // same
console.log(_.toNumber([1]), parseInt([1])) // same
console.log(_.toNumber(' 1a1 '), parseInt(' 1a1 ')) // NaN 1
console.log(_.toNumber([1,2]), parseInt([1,2])) // NaN 1
console.log(_.toNumber(false), parseInt(false)) // 0 NaN
console.log(_.toNumber(!0), parseInt(!0)) // 1 NaN
console.log(_.toNumber(!!0), parseInt(!!0)) // 0 NaN
console.log(_.toNumber(5e-324), parseInt(5e-324)) // 5e-324 5
console.log(_.toNumber(5.5), parseInt(5.5)) // 5.5 5
console.log(_.toNumber(null), parseInt(null)) // 0 NaN
console.log(_.toNumber(Infinity),parseInt(Infinity)) // Infinity NaN
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
So to summarize _.isNumber gives you more expected / consistent and I would argue safer results when it comes to parsing input with arrays, decimals, falsy values and strings. It would check the entire input vs parseInt which only cares about the first valid value as you can see from the examples above. It also handles better the negate operator (!) etc.
So overall it does have its uses vs parseInt
Note: What is a gotcha here is that both _.toNumber and parseInt return NaN for undefined which considering how _.toNumber deals with the rest of the falsy values one would expect to return 0 vs NaN:
console.log(_.toNumber(undefined), parseInt(undefined)) // NaN NaN

_.toNumber converts a given input to a number if such a conversion is possible, otherwise returns NaN. The parseInt and parseFloat methods also work in same manner (the former will only return integers though), however, they are much more lax in their parsing rules. _.toNumber is significantly more restrictive.
For eg, with same input '5.2a', parseInt would return 5, parseFloat would return 5.2, and _.toNumber would return NaN. The former two ignore everything after the first unrecognised character and return the number formed by all parsed characters till that point. The last one however returns NaN if an unrecognised character is encountered.
_.toNumber is comparable and functionally same to Number function.

Related

getting wrong answer for finding largest of 2 numbers using readline-sync in js [duplicate]

I store some parameters client-side in HTML and then need to compare them as integers. Unfortunately I have come across a serious bug that I cannot explain. The bug seems to be that my JS reads parameters as strings rather than integers, causing my integer comparisons to fail.
I have generated a small example of the error, which I also can't explain. The following returns 'true' when run:
console.log("2" > "10")
Parse the string into an integer using parseInt:
javascript:alert(parseInt("2", 10)>parseInt("10", 10))
Checking that strings are integers is separate to comparing if one is greater or lesser than another. You should always compare number with number and string with string as the algorithm for dealing with mixed types not easy to remember.
'00100' < '1' // true
as they are both strings so only the first zero of '00100' is compared to '1' and because it's charCode is lower, it evaluates as lower.
However:
'00100' < 1 // false
as the RHS is a number, the LHS is converted to number before the comparision.
A simple integer check is:
function isInt(n) {
return /^[+-]?\d+$/.test(n);
}
It doesn't matter if n is a number or integer, it will be converted to a string before the test.
If you really care about performance, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
return function(n) {
return re.test(n);
}
}());
Noting that numbers like 1.0 will return false. If you want to count such numbers as integers too, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
var re2 = /\.0+$/;
return function(n) {
return re.test((''+ n).replace(re2,''));
}
}());
Once that test is passed, converting to number for comparison can use a number of methods. I don't like parseInt() because it will truncate floats to make them look like ints, so all the following will be "equal":
parseInt(2.9) == parseInt('002',10) == parseInt('2wewe')
and so on.
Once numbers are tested as integers, you can use the unary + operator to convert them to numbers in the comparision:
if (isInt(a) && isInt(b)) {
if (+a < +b) {
// a and b are integers and a is less than b
}
}
Other methods are:
Number(a); // liked by some because it's clear what is happening
a * 1 // Not really obvious but it works, I don't like it
Comparing Numbers to String Equivalents Without Using parseInt
console.log(Number('2') > Number('10'));
console.log( ('2'/1) > ('10'/1) );
var item = { id: 998 }, id = '998';
var isEqual = (item.id.toString() === id.toString());
isEqual;
use parseInt and compare like below:
javascript:alert(parseInt("2")>parseInt("10"))
Always remember when we compare two strings.
the comparison happens on chacracter basis.
so '2' > '12' is true because the comparison will happen as
'2' > '1' and in alphabetical way '2' is always greater than '1' as unicode.
SO it will comeout true.
I hope this helps.
You can use Number() function also since it converts the object argument to a number that represents the object's value.
Eg: javascript:alert( Number("2") > Number("10"))
+ operator will coerce the string to a number.
console.log( +"2" > +"10" )
The answer is simple. Just divide string by 1.
Examples:
"2" > "10" - true
but
"2"/1 > "10"/1 - false
Also you can check if string value really is number:
!isNaN("1"/1) - true (number)
!isNaN("1a"/1) - false (string)
!isNaN("01"/1) - true (number)
!isNaN(" 1"/1) - true (number)
!isNaN(" 1abc"/1) - false (string)
But
!isNaN(""/1) - true (but string)
Solution
number !== "" && !isNaN(number/1)
The alert() wants to display a string, so it will interpret "2">"10" as a string.
Use the following:
var greater = parseInt("2") > parseInt("10");
alert("Is greater than? " + greater);
var less = parseInt("2") < parseInt("10");
alert("Is less than? " + less);

Javascript: NaN vs typeof Number [duplicate]

I'm hoping there's something in the same conceptual space as the old VB6 IsNumeric() function?
2nd October 2020: note that many bare-bones approaches are fraught with subtle bugs (eg. whitespace, implicit partial parsing, radix, coercion of arrays etc.) that many of the answers here fail to take into account. The following implementation might work for you, but note that it does not cater for number separators other than the decimal point ".":
function isNumeric(str) {
if (typeof str != "string") return false // we only process strings!
return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
!isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
}
To check if a variable (including a string) is a number, check if it is not a number:
This works regardless of whether the variable content is a string or number.
isNaN(num) // returns true if the variable does NOT contain a valid number
Examples
isNaN(123) // false
isNaN('123') // false
isNaN('1e10000') // false (This translates to Infinity, which is a number)
isNaN('foo') // true
isNaN('10px') // true
isNaN('') // false
isNaN(' ') // false
isNaN(false) // false
Of course, you can negate this if you need to. For example, to implement the IsNumeric example you gave:
function isNumeric(num){
return !isNaN(num)
}
To convert a string containing a number into a number:
Only works if the string only contains numeric characters, else it returns NaN.
+num // returns the numeric value of the string, or NaN
// if the string isn't purely numeric characters
Examples
+'12' // 12
+'12.' // 12
+'12..' // NaN
+'.12' // 0.12
+'..12' // NaN
+'foo' // NaN
+'12px' // NaN
To convert a string loosely to a number
Useful for converting '12px' to 12, for example:
parseInt(num) // extracts a numeric value from the
// start of the string, or NaN.
Examples
parseInt('12') // 12
parseInt('aaa') // NaN
parseInt('12px') // 12
parseInt('foo2') // NaN These last three may
parseInt('12a5') // 12 be different from what
parseInt('0x10') // 16 you expected to see.
Floats
Bear in mind that, unlike +num, parseInt (as the name suggests) will convert a float into an integer by chopping off everything following the decimal point (if you want to use parseInt() because of this behaviour, you're probably better off using another method instead):
+'12.345' // 12.345
parseInt(12.345) // 12
parseInt('12.345') // 12
Empty strings
Empty strings may be a little counter-intuitive. +num converts empty strings or strings with spaces to zero, and isNaN() assumes the same:
+'' // 0
+' ' // 0
isNaN('') // false
isNaN(' ') // false
But parseInt() does not agree:
parseInt('') // NaN
parseInt(' ') // NaN
If you're just trying to check if a string is a whole number (no decimal places), regex is a good way to go. Other methods such as isNaN are too complicated for something so simple.
function isNumeric(value) {
return /^-?\d+$/.test(value);
}
console.log(isNumeric('abcd')); // false
console.log(isNumeric('123a')); // false
console.log(isNumeric('1')); // true
console.log(isNumeric('1234567890')); // true
console.log(isNumeric('-23')); // true
console.log(isNumeric(1234)); // true
console.log(isNumeric(1234n)); // true
console.log(isNumeric('123.4')); // false
console.log(isNumeric('')); // false
console.log(isNumeric(undefined)); // false
console.log(isNumeric(null)); // false
To only allow positive whole numbers use this:
function isNumeric(value) {
return /^\d+$/.test(value);
}
console.log(isNumeric('123')); // true
console.log(isNumeric('-23')); // false
The accepted answer for this question has quite a few flaws (as highlighted by couple of other users). This is one of the easiest & proven way to approach it in javascript:
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
Below are some good test cases:
console.log(isNumeric(12345678912345678912)); // true
console.log(isNumeric('2 ')); // true
console.log(isNumeric('-32.2 ')); // true
console.log(isNumeric(-32.2)); // true
console.log(isNumeric(undefined)); // false
// the accepted answer fails at these tests:
console.log(isNumeric('')); // false
console.log(isNumeric(null)); // false
console.log(isNumeric([])); // false
And you could go the RegExp-way:
var num = "987238";
if(num.match(/^-?\d+$/)){
//valid integer (positive or negative)
}else if(num.match(/^\d+\.\d+$/)){
//valid float
}else{
//not valid number
}
If you really want to make sure that a string contains only a number, any number (integer or floating point), and exactly a number, you cannot use parseInt()/ parseFloat(), Number(), or !isNaN() by themselves. Note that !isNaN() is actually returning true when Number() would return a number, and false when it would return NaN, so I will exclude it from the rest of the discussion.
The problem with parseFloat() is that it will return a number if the string contains any number, even if the string doesn't contain only and exactly a number:
parseFloat("2016-12-31") // returns 2016
parseFloat("1-1") // return 1
parseFloat("1.2.3") // returns 1.2
The problem with Number() is that it will return a number in cases where the passed value is not a number at all!
Number("") // returns 0
Number(" ") // returns 0
Number(" \u00A0 \t\n\r") // returns 0
The problem with rolling your own regex is that unless you create the exact regex for matching a floating point number as Javascript recognizes it you are going to miss cases or recognize cases where you shouldn't. And even if you can roll your own regex, why? There are simpler built-in ways to do it.
However, it turns out that Number() (and isNaN()) does the right thing for every case where parseFloat() returns a number when it shouldn't, and vice versa. So to find out if a string is really exactly and only a number, call both functions and see if they both return true:
function isNumber(str) {
if (typeof str != "string") return false // we only process strings!
// could also coerce to string: str = ""+str
return !isNaN(str) && !isNaN(parseFloat(str))
}
Try the isNan function:
The isNaN() function determines whether a value is an illegal number (Not-a-Number).
This function returns true if the value equates to NaN. Otherwise it returns false.
This function is different from the Number specific Number.isNaN() method.
The global isNaN() function, converts the tested value to a Number, then tests it.
Number.isNan() does not convert the values to a Number, and will not return true for any value that is not of the type Number...
2019: Including ES3, ES6 and TypeScript Examples
Maybe this has been rehashed too many times, however I fought with this one today too and wanted to post my answer, as I didn't see any other answer that does it as simply or thoroughly:
ES3
var isNumeric = function(num){
return (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);
}
ES6
const isNumeric = (num) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);
Typescript
const isNumeric = (num: any) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num as number);
This seems quite simple and covers all the bases I saw on the many other posts and thought up myself:
// Positive Cases
console.log(0, isNumeric(0) === true);
console.log(1, isNumeric(1) === true);
console.log(1234567890, isNumeric(1234567890) === true);
console.log('1234567890', isNumeric('1234567890') === true);
console.log('0', isNumeric('0') === true);
console.log('1', isNumeric('1') === true);
console.log('1.1', isNumeric('1.1') === true);
console.log('-1', isNumeric('-1') === true);
console.log('-1.2354', isNumeric('-1.2354') === true);
console.log('-1234567890', isNumeric('-1234567890') === true);
console.log(-1, isNumeric(-1) === true);
console.log(-32.1, isNumeric(-32.1) === true);
console.log('0x1', isNumeric('0x1') === true); // Valid number in hex
// Negative Cases
console.log(true, isNumeric(true) === false);
console.log(false, isNumeric(false) === false);
console.log('1..1', isNumeric('1..1') === false);
console.log('1,1', isNumeric('1,1') === false);
console.log('-32.1.12', isNumeric('-32.1.12') === false);
console.log('[blank]', isNumeric('') === false);
console.log('[spaces]', isNumeric(' ') === false);
console.log('null', isNumeric(null) === false);
console.log('undefined', isNumeric(undefined) === false);
console.log([], isNumeric([]) === false);
console.log('NaN', isNumeric(NaN) === false);
You can also try your own isNumeric function and just past in these use cases and scan for "true" for all of them.
Or, to see the values that each return:
Old question, but there are several points missing in the given answers.
Scientific notation.
!isNaN('1e+30') is true, however in most of the cases when people ask for numbers, they do not want to match things like 1e+30.
Large floating numbers may behave weird
Observe (using Node.js):
> var s = Array(16 + 1).join('9')
undefined
> s.length
16
> s
'9999999999999999'
> !isNaN(s)
true
> Number(s)
10000000000000000
> String(Number(s)) === s
false
>
On the other hand:
> var s = Array(16 + 1).join('1')
undefined
> String(Number(s)) === s
true
> var s = Array(15 + 1).join('9')
undefined
> String(Number(s)) === s
true
>
So, if one expects String(Number(s)) === s, then better limit your strings to 15 digits at most (after omitting leading zeros).
Infinity
> typeof Infinity
'number'
> !isNaN('Infinity')
true
> isFinite('Infinity')
false
>
Given all that, checking that the given string is a number satisfying all of the following:
non scientific notation
predictable conversion to Number and back to String
finite
is not such an easy task. Here is a simple version:
function isNonScientificNumberString(o) {
if (!o || typeof o !== 'string') {
// Should not be given anything but strings.
return false;
}
return o.length <= 15 && o.indexOf('e+') < 0 && o.indexOf('E+') < 0 && !isNaN(o) && isFinite(o);
}
However, even this one is far from complete. Leading zeros are not handled here, but they do screw the length test.
I have tested and Michael's solution is best. Vote for his answer above (search this page for "If you really want to make sure that a string" to find it). In essence, his answer is this:
function isNumeric(num){
num = "" + num; //coerce num to be a string
return !isNaN(num) && !isNaN(parseFloat(num));
}
It works for every test case, which I documented here:
https://jsfiddle.net/wggehvp9/5/
Many of the other solutions fail for these edge cases:
' ', null, "", true, and [].
In theory, you could use them, with proper error handling, for example:
return !isNaN(num);
or
return (+num === +num);
with special handling for
/\s/, null, "", true, false, [] (and others?)
TL;DR
It depends largely on what you want to parse as a number.
Comparison Between Built-in Functions
As none of the existing sources satisfied my soul, I tried to figure out what actually was happening with these functions.
Three immediate answers to this question felt like:
!isNaN(input) (which gives the same output as +input === +input)
!isNaN(parseFloat(input))
isFinite(input)
But are any of them correct in every scenario?
I tested these functions in several cases, and generated output as markdown. This is what it looks like:
input
!isNaN(input) or +input===+input
!isNaN(parseFloat(input))
isFinite(input)
Comment
123
✔️
✔️
✔️
-
'123'
✔️
✔️
✔️
-
12.3
✔️
✔️
✔️
-
'12.3'
✔️
✔️
✔️
-
'   12.3   '
✔️
✔️
✔️
Empty whitespace trimmed, as expected.
1_000_000
✔️
✔️
✔️
Numeric separator understood, also expected.
'1_000_000'
❌
✔️
❌
Surprise! JS just won't parse numeric separator inside a string. For details, check this issue. (Why then parsing as float worked though? Well, it didn't. 😉)
'0b11111111'
✔️
✔️
✔️
Binary form understood, as it should've.
'0o377'
✔️
✔️
✔️
Octal form understood too.
'0xFF'
✔️
✔️
✔️
Of course hex is understood. Did anybody think otherwise? 😒
''
✔️
❌
✔️
Should empty string be a number?
'    '
✔️
❌
✔️
Should a whitespace-only string be a number?
'abc'
❌
❌
❌
Everybody agrees, not a number.
'12.34Ab!##$'
❌
✔️
❌
Ah! Now it's quite understandable what parseFloat() does. Not impressive to me, but may come handy in certain cases.
'10e100'
✔️
✔️
✔️
10100 is a number indeed. But caution! It's way more larger than the maximum safe integer value 253 (about 9×1015). Read this for details.
'10e1000'
✔️
✔️
❌
Say with me, help! Though not as crazy as it may seem. In JavaScript, a value larger than ~10308 is rounded to infinity, that's why. Look here for details. And yes, isNaN() considers infinity as a number, and parseFloat() parses infinity as infinity.
null
✔️
❌
✔️
Now this is awkward. In JS, when a conversion is needed, null becomes zero, and we get a finite number. Then why parseFloat(null) should return a NaN here? Someone please explain this design concept to me.
undefined
❌
❌
❌
As expected.
Infinity
✔️
✔️
❌
As explained before, isNaN() considers infinity as a number, and parseFloat() parses infinity as infinity.
So...which of them is "correct"?
Should be clear by now, it depends largely on what we need. For example, we may want to consider a null input as 0. In that case isFinite() will work fine.
Again, perhaps we will take a little help from isNaN() when 1010000000000 is needed to be considered a valid number (although the question remains—why would it be, and how would we handle that)!
Of course, we can manually exclude any of the scenarios.
Like in my case, I needed exactly the outputs of isFinite(), except for the null case, the empty string case, and the whitespace-only string case. Also I had no headache about really huge numbers. So my code looked like this:
/**
* My necessity was met by the following code.
*/
if (input === null) {
// Null input
} else if (input.trim() === '') {
// Empty or whitespace-only string
} else if (isFinite(input)) {
// Input is a number
} else {
// Not a number
}
And also, this was my JavaScript to generate the table:
/**
* Note: JavaScript does not print numeric separator inside a number.
* In that single case, the markdown output was manually corrected.
* Also, the comments were manually added later, of course.
*/
let inputs = [
123, '123', 12.3, '12.3', ' 12.3 ',
1_000_000, '1_000_000',
'0b11111111', '0o377', '0xFF',
'', ' ',
'abc', '12.34Ab!##$',
'10e100', '10e1000',
null, undefined, Infinity];
let markdownOutput = `| \`input\` | \`!isNaN(input)\` or <br>\`+input === +input\` | \`!isNaN(parseFloat(input))\` | \`isFinite(input)\` | Comment |
| :---: | :---: | :---: | :---: | :--- |\n`;
for (let input of inputs) {
let outputs = [];
outputs.push(!isNaN(input));
outputs.push(!isNaN(parseFloat(input)));
outputs.push(isFinite(input));
if (typeof input === 'string') {
// Output with quotations
console.log(`'${input}'`);
markdownOutput += `| '${input}'`;
} else {
// Output without quotes
console.log(input);
markdownOutput += `| ${input}`;
}
for (let output of outputs) {
console.log('\t' + output);
if (output === true) {
markdownOutput += ` | <div style="color:limegreen">true</div>`;
// markdownOutput += ` | ✔️`; // for stackoverflow
} else {
markdownOutput += ` | <div style="color:orangered">false</div>`;
// markdownOutput += ` | ❌`; // for stackoverflow
}
}
markdownOutput += ` ||\n`;
}
// Replace two or more whitespaces with $nbsp;
markdownOutput = markdownOutput.replaceAll(` `, ` `);
// Print markdown to console
console.log(markdownOutput);
The JavaScript global isFinite() checks if a value is a valid (finite) number.
See MDN for the difference between Number.isFinite() and global isFinite().
let a = isFinite('abc') // false
let b = isFinite('123') // true
let c = isFinite('12a') // false
let d = isFinite(null) // true
console.log(a, b, c, d)
Someone may also benefit from a regex based answer. Here it is:
One liner isInteger:
const isInteger = num => /^-?[0-9]+$/.test(num+'');
One liner isNumeric: Accepts integers and decimals
const isNumeric = num => /^-?[0-9]+(?:\.[0-9]+)?$/.test(num+'');
You can use the result of Number when passing an argument to its constructor.
If the argument (a string) cannot be converted into a number, it returns NaN, so you can determinate if the string provided was a valid number or not.
Notes: Note when passing empty string or '\t\t' and '\n\t' as Number will return 0; Passing true will return 1 and false returns 0.
Number('34.00') // 34
Number('-34') // -34
Number('123e5') // 12300000
Number('123e-5') // 0.00123
Number('999999999999') // 999999999999
Number('9999999999999999') // 10000000000000000 (integer accuracy up to 15 digit)
Number('0xFF') // 255
Number('Infinity') // Infinity
Number('34px') // NaN
Number('xyz') // NaN
Number('true') // NaN
Number('false') // NaN
// cavets
Number(' ') // 0
Number('\t\t') // 0
Number('\n\t') // 0
Maybe there are one or two people coming across this question who need a much stricter check than usual (like I did). In that case, this might be useful:
if(str === String(Number(str))) {
// it's a "perfectly formatted" number
}
Beware! This will reject strings like .1, 40.000, 080, 00.1. It's very picky - the string must match the "most minimal perfect form" of the number for this test to pass.
It uses the String and Number constructor to cast the string to a number and back again and thus checks if the JavaScript engine's "perfect minimal form" (the one it got converted to with the initial Number constructor) matches the original string.
Why is jQuery's implementation not good enough?
function isNumeric(a) {
var b = a && a.toString();
return !$.isArray(a) && b - parseFloat(b) + 1 >= 0;
};
Michael suggested something like this (although I've stolen "user1691651 - John"'s altered version here):
function isNumeric(num){
num = "" + num; //coerce num to be a string
return !isNaN(num) && !isNaN(parseFloat(num));
}
The following is a solution with most likely bad performance, but solid results. It is a contraption made from the jQuery 1.12.4 implementation and Michael's answer, with an extra check for leading/trailing spaces (because Michael's version returns true for numerics with leading/trailing spaces):
function isNumeric(a) {
var str = a + "";
var b = a && a.toString();
return !$.isArray(a) && b - parseFloat(b) + 1 >= 0 &&
!/^\s+|\s+$/g.test(str) &&
!isNaN(str) && !isNaN(parseFloat(str));
};
The latter version has two new variables, though. One could get around one of those, by doing:
function isNumeric(a) {
if ($.isArray(a)) return false;
var b = a && a.toString();
a = a + "";
return b - parseFloat(b) + 1 >= 0 &&
!/^\s+|\s+$/g.test(a) &&
!isNaN(a) && !isNaN(parseFloat(a));
};
I haven't tested any of these very much, by other means than manually testing the few use-cases I'll be hitting with my current predicament, which is all very standard stuff. This is a "standing-on-the-shoulders-of-giants" situation.
2019: Practical and tight numerical validity check
Often, a 'valid number' means a Javascript number excluding NaN and Infinity, ie a 'finite number'.
To check the numerical validity of a value (from an external source for example), you can define in ESlint Airbnb style :
/**
* Returns true if 'candidate' is a finite number or a string referring (not just 'including') a finite number
* To keep in mind:
* Number(true) = 1
* Number('') = 0
* Number(" 10 ") = 10
* !isNaN(true) = true
* parseFloat('10 a') = 10
*
* #param {?} candidate
* #return {boolean}
*/
function isReferringFiniteNumber(candidate) {
if (typeof (candidate) === 'number') return Number.isFinite(candidate);
if (typeof (candidate) === 'string') {
return (candidate.trim() !== '') && Number.isFinite(Number(candidate));
}
return false;
}
and use it this way:
if (isReferringFiniteNumber(theirValue)) {
myCheckedValue = Number(theirValue);
} else {
console.warn('The provided value doesn\'t refer to a finite number');
}
It is not valid for TypeScript as:
declare function isNaN(number: number): boolean;
For TypeScript you can use:
/^\d+$/.test(key)
I like the simplicity of this.
Number.isNaN(Number(value))
The above is regular Javascript, but I'm using this in conjunction with a typescript typeguard for smart type checking. This is very useful for the typescript compiler to give you correct intellisense, and no type errors.
Typescript typeguards
Warning: See Jeremy's comment below. This has some issues with certain values and I don't have time to fix it now, but the idea of using a typescript typeguard is useful so I won't delete this section.
isNotNumber(value: string | number): value is string {
return Number.isNaN(Number(this.smartImageWidth));
}
isNumber(value: string | number): value is number {
return Number.isNaN(Number(this.smartImageWidth)) === false;
}
Let's say you have a property width which is number | string. You may want to do logic based on whether or not it's a string.
var width: number|string;
width = "100vw";
if (isNotNumber(width))
{
// the compiler knows that width here must be a string
if (width.endsWith('vw'))
{
// we have a 'width' such as 100vw
}
}
else
{
// the compiler is smart and knows width here must be number
var doubleWidth = width * 2;
}
The typeguard is smart enough to constrain the type of width within the if statement to be ONLY string. This permits the compiler to allow width.endsWith(...) which it wouldn't allow if the type was string | number.
You can call the typeguard whatever you want isNotNumber, isNumber, isString, isNotString but I think isString is kind of ambiguous and harder to read.
parseInt(), but be aware that this function is a bit different in the sense that it for example returns 100 for parseInt("100px").
When guarding against empty strings and null
// Base cases that are handled properly
Number.isNaN(Number('1')); // => false
Number.isNaN(Number('-1')); // => false
Number.isNaN(Number('1.1')); // => false
Number.isNaN(Number('-1.1')); // => false
Number.isNaN(Number('asdf')); // => true
Number.isNaN(Number(undefined)); // => true
// Special notation cases that are handled properly
Number.isNaN(Number('1e1')); // => false
Number.isNaN(Number('1e-1')); // => false
Number.isNaN(Number('-1e1')); // => false
Number.isNaN(Number('-1e-1')); // => false
Number.isNaN(Number('0b1')); // => false
Number.isNaN(Number('0o1')); // => false
Number.isNaN(Number('0xa')); // => false
// Edge cases that will FAIL if not guarded against
Number.isNaN(Number('')); // => false
Number.isNaN(Number(' ')); // => false
Number.isNaN(Number(null)); // => false
// Edge cases that are debatable
Number.isNaN(Number('-0b1')); // => true
Number.isNaN(Number('-0o1')); // => true
Number.isNaN(Number('-0xa')); // => true
Number.isNaN(Number('Infinity')); // => false
Number.isNaN(Number('INFINITY')); // => true
Number.isNaN(Number('-Infinity')); // => false
Number.isNaN(Number('-INFINITY')); // => true
When NOT guarding against empty strings and null
Using parseInt:
// Base cases that are handled properly
Number.isNaN(parseInt('1')); // => false
Number.isNaN(parseInt('-1')); // => false
Number.isNaN(parseInt('1.1')); // => false
Number.isNaN(parseInt('-1.1')); // => false
Number.isNaN(parseInt('asdf')); // => true
Number.isNaN(parseInt(undefined)); // => true
Number.isNaN(parseInt('')); // => true
Number.isNaN(parseInt(' ')); // => true
Number.isNaN(parseInt(null)); // => true
// Special notation cases that are handled properly
Number.isNaN(parseInt('1e1')); // => false
Number.isNaN(parseInt('1e-1')); // => false
Number.isNaN(parseInt('-1e1')); // => false
Number.isNaN(parseInt('-1e-1')); // => false
Number.isNaN(parseInt('0b1')); // => false
Number.isNaN(parseInt('0o1')); // => false
Number.isNaN(parseInt('0xa')); // => false
// Edge cases that are debatable
Number.isNaN(parseInt('-0b1')); // => false
Number.isNaN(parseInt('-0o1')); // => false
Number.isNaN(parseInt('-0xa')); // => false
Number.isNaN(parseInt('Infinity')); // => true
Number.isNaN(parseInt('INFINITY')); // => true
Number.isNaN(parseInt('-Infinity')); // => true
Number.isNaN(parseInt('-INFINITY')); // => true
Using parseFloat:
// Base cases that are handled properly
Number.isNaN(parseFloat('1')); // => false
Number.isNaN(parseFloat('-1')); // => false
Number.isNaN(parseFloat('1.1')); // => false
Number.isNaN(parseFloat('-1.1')); // => false
Number.isNaN(parseFloat('asdf')); // => true
Number.isNaN(parseFloat(undefined)); // => true
Number.isNaN(parseFloat('')); // => true
Number.isNaN(parseFloat(' ')); // => true
Number.isNaN(parseFloat(null)); // => true
// Special notation cases that are handled properly
Number.isNaN(parseFloat('1e1')); // => false
Number.isNaN(parseFloat('1e-1')); // => false
Number.isNaN(parseFloat('-1e1')); // => false
Number.isNaN(parseFloat('-1e-1')); // => false
Number.isNaN(parseFloat('0b1')); // => false
Number.isNaN(parseFloat('0o1')); // => false
Number.isNaN(parseFloat('0xa')); // => false
// Edge cases that are debatable
Number.isNaN(parseFloat('-0b1')); // => false
Number.isNaN(parseFloat('-0o1')); // => false
Number.isNaN(parseFloat('-0xa')); // => false
Number.isNaN(parseFloat('Infinity')); // => false
Number.isNaN(parseFloat('INFINITY')); // => true
Number.isNaN(parseFloat('-Infinity')); // => false
Number.isNaN(parseFloat('-INFINITY')); // => true
Notes:
Only string, empty, and uninitialized values are considered in keeping with addressing the original question. Additional edge cases exist if arrays and objects are the values being considered.
Characters in binary, octal, hexadecimal, and exponential notation are not case-sensitive (ie: '0xFF', '0XFF', '0xfF' etc. will all yield the same result in the test cases shown above).
Unlike with Infinity (case-sensitive) in some cases, constants from the Number and Math objects passed as test cases in string format to any of the methods above will be determined to not be numbers.
See here for an explanation of how arguments are converted to a Number and why the edge cases for null and empty strings exist.
Quote:
isNaN(num) // returns true if the variable does NOT contain a valid number
is not entirely true if you need to check for leading/trailing spaces - for example when a certain quantity of digits is required, and you need to get, say, '1111' and not ' 111' or '111 ' for perhaps a PIN input.
Better to use:
var num = /^\d+$/.test(num)
This is built on some of the previous answers and comments. The following covers all the edge cases and fairly concise as well:
const isNumRegEx = /^-?(\d*\.)?\d+$/;
function isNumeric(n, allowScientificNotation = false) {
return allowScientificNotation ?
!Number.isNaN(parseFloat(n)) && Number.isFinite(n) :
isNumRegEx.test(n);
}
If anyone ever gets this far down, I spent some time hacking on this trying to patch moment.js (https://github.com/moment/moment). Here's something that I took away from it:
function isNumeric(val) {
var _val = +val;
return (val !== val + 1) //infinity check
&& (_val === +val) //Cute coercion check
&& (typeof val !== 'object') //Array/object check
}
Handles the following cases:
True! :
isNumeric("1"))
isNumeric(1e10))
isNumeric(1E10))
isNumeric(+"6e4"))
isNumeric("1.2222"))
isNumeric("-1.2222"))
isNumeric("-1.222200000000000000"))
isNumeric("1.222200000000000000"))
isNumeric(1))
isNumeric(0))
isNumeric(-0))
isNumeric(1010010293029))
isNumeric(1.100393830000))
isNumeric(Math.LN2))
isNumeric(Math.PI))
isNumeric(5e10))
False! :
isNumeric(NaN))
isNumeric(Infinity))
isNumeric(-Infinity))
isNumeric())
isNumeric(undefined))
isNumeric('[1,2,3]'))
isNumeric({a:1,b:2}))
isNumeric(null))
isNumeric([1]))
isNumeric(new Date()))
Ironically, the one I am struggling with the most:
isNumeric(new Number(1)) => false
Any suggestions welcome. :]
I recently wrote an article about ways to ensure a variable is a valid number: https://github.com/jehugaleahsa/artifacts/blob/master/2018/typescript_num_hack.md The article explains how to ensure floating point or integer, if that's important (+x vs ~~x).
The article assumes the variable is a string or a number to begin with and trim is available/polyfilled. It wouldn't be hard to extend it to handle other types, as well. Here's the meat of it:
// Check for a valid float
if (x == null
|| ("" + x).trim() === ""
|| isNaN(+x)) {
return false; // not a float
}
// Check for a valid integer
if (x == null
|| ("" + x).trim() === ""
|| ~~x !== +x) {
return false; // not an integer
}
function isNumberCandidate(s) {
const str = (''+ s).trim();
if (str.length === 0) return false;
return !isNaN(+str);
}
console.log(isNumberCandidate('1')); // true
console.log(isNumberCandidate('a')); // false
console.log(isNumberCandidate('000')); // true
console.log(isNumberCandidate('1a')); // false
console.log(isNumberCandidate('1e')); // false
console.log(isNumberCandidate('1e-1')); // true
console.log(isNumberCandidate('123.3')); // true
console.log(isNumberCandidate('')); // false
console.log(isNumberCandidate(' ')); // false
console.log(isNumberCandidate(1)); // true
console.log(isNumberCandidate(0)); // true
console.log(isNumberCandidate(NaN)); // false
console.log(isNumberCandidate(undefined)); // false
console.log(isNumberCandidate(null)); // false
console.log(isNumberCandidate(-1)); // true
console.log(isNumberCandidate('-1')); // true
console.log(isNumberCandidate('-1.2')); // true
console.log(isNumberCandidate(0.0000001)); // true
console.log(isNumberCandidate('0.0000001')); // true
console.log(isNumberCandidate(Infinity)); // true
console.log(isNumberCandidate(-Infinity)); // true
console.log(isNumberCandidate('Infinity')); // true
if (isNumberCandidate(s)) {
// use +s as a number
+s ...
}
Well, I'm using this one I made...
It's been working so far:
function checkNumber(value) {
return value % 1 == 0;
}
If you spot any problem with it, tell me, please.
Checking the number in JS:
Best way for check if it's a number:
isFinite(20)
//True
Read a value out of a string. CSS *:
parseInt('2.5rem')
//2
parseFloat('2.5rem')
//2.5
For an integer:
isInteger(23 / 0)
//False
If value is NaN:
isNaN(20)
//False
This way it works for me.
function isNumeric(num){
let value1 = num.toString();
let value2 = parseFloat(num).toString();
return (value1 === value2);
}
console.log(
isNumeric(123), //true
isNumeric(-123), //true
isNumeric('123'), //true
isNumeric('-123'), //true
isNumeric(12.2), //true
isNumeric(-12.2), //true
isNumeric('12.2'), //true
isNumeric('-12.2'), //true
isNumeric('a123'), //false
isNumeric('123a'), //false
isNumeric(' 123'), //false
isNumeric('123 '), //false
isNumeric('a12.2'), //false
isNumeric('12.2a'), //false
isNumeric(' 12.2'), //false
isNumeric('12.2 '), //false
)
PFB the working solution:
function(check){
check = check + "";
var isNumber = check.trim().length>0? !isNaN(check):false;
return isNumber;
}
Save yourself the headache of trying to find a "built-in" solution.
There isn't a good answer, and the hugely upvoted answer in this thread is wrong.
npm install is-number
In JavaScript, it's not always as straightforward as it should be to reliably check if a value is a number. It's common for devs to use +, -, or Number() to cast a string value to a number (for example, when values are returned from user input, regex matches, parsers, etc). But there are many non-intuitive edge cases that yield unexpected results:
console.log(+[]); //=> 0
console.log(+''); //=> 0
console.log(+' '); //=> 0
console.log(typeof NaN); //=> 'number'

How to check equality of NaN javascript [duplicate]

This question already has answers here:
How do you check that a number is NaN in JavaScript?
(33 answers)
Closed 3 years ago.
I have been trying to check the value and type of NaN for equality but I am getting errors every time. It seems like there must be a simpler solution. Here are four possible solutions I have tried so far that do not work. Another thing is that the underscore in the first solution is not recognized on edabit or codepen:
solution 1
function checkEquality(a, b) {
if((typeof a === typeof b) ||
(_.isNaN(a) === true) &&
(_.isNaN(b) === true)) {
return true;
}
}
solution 2
function checkEquality(a, b) {
let divisionByZod = 42 / "General Zod";
let valueIsNaN = (divisionByZod !== divisionByZod);
if((typeof a === typeof b) || (42 / 'General Zod' === true)) {
return true;
}
}
solution 3
function checkEquality(a, b) {
if(((typeof a === typeof b) || (isNaN(parseInt(NaN))))) {
return true;
}
}
solution 4
function checkEquality(a, b) {
let c = NaN;
if(((typeof a !== typeof b) || (isNaN(parseInt(c) !== NaN)))) {
return false;
}
}
The best option to check if a variable is not a number is the isNan() function.
https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/isNaN
Is good to observe that :
Unlike all other possible values in JavaScript, it is not possible to rely on the equality operators (== and ===) to determine whether a value is NaN or not, because both NaN == NaN and NaN === NaN evaluate to false. Hence, the necessity of an isNaN function.
I don't know your use case but take in consideration that it is not possible to rely on the equality operators (== and ===) to determine whether two objects are equal or not, to this purpose the best is use Object.is() function
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
Observe that :
Object.is() determines whether two values are the same value. Two values are the same if one of the following holds:
both undefined
both null
both true or both false
both strings of the same length with the same characters in the same order
both the same object (means both object have same reference)
both numbers and
both +0
both -0
both NaN
or both non-zero and both not NaN and both have the same value
This is not the same as being equal according to the == operator. The == operator applies various coercions to both sides (if they are not the same Type) before testing for equality (resulting in such behavior as "" == false being true), but Object.is doesn't coerce either value.
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.
Knowing that I think that Object.is(a,b) is the solution for your problem.
const nan1 = 'a string' / 2
const nan2 = 'another string' / 2
const comparation = Object.is(nan1,nan2)
console.log(comparation) // true
if (isNaN(x)) {
return 'Not a Number!';
}
isNaN is the function you are looking for
Try function isNaN(). Returns true if value NaN
Try to use the Object.is() method. It determines whether two values are the same value. Two values are the same if one of the following holds:
both undefined
both null
both true or both false
both strings of the same length with the same characters in the same order
both the same object (means both object have same reference)
both numbers and
both +0
both -0
both NaN
or both non-zero and both not NaN and both have the same value
Refer to the following documentation which
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is

Integer validation not working as expected

Thanks to some of the answers on this site, I built a function to validate an integer inside a prompt in javascript. I found out how to use isNaN and the result of % in order to meet my needs, but there must be something wrong, because is still not working: This function for validation needs to accept only integers, and as extra bonus, it will also accept a special keyword used for a different purpose later on in the program.
So, previously I had defined:
var value = prompt("Type an integer");
So after that, I made a call for the validation function, and that included three conditions: The validation warning would jump if:
1) The string is not a number
2) The string % 1 is not 0 (means is not an integer)
3) The string is not the special keyword ("extra") which is also valid as input.
The function needs to loop and keep showing the prompt until a valid data is written.
while (isNaN(value) == true && value % 1 != 0 && value != "extra") {
alert("Please, type an integer");
var value = prompt("Type an integer");
}
What am I doing wrong? Thank you so much for any ideas. I know the integer validation has been asked many times here, and here I got a few ideas, but I might be missing something...
You might be complicating things too much... A quick regular expression will do the trick.
while (!/^(\d+|extra)$/i.test(value)) {
...
}
You typed only one equal at
isNaN(value) = true
jsFiddle example
var int = 10;
var str = "10";
var isInt = function(value) {
return (str === 'extra' || !isNaN(parseInt(value, 16)) || /^\d+$/.test(value));
};
var isIntStrict = function(value) {
return (isInt(value) && typeof value !== 'string');
}
console.log('false', isInt('kirk'));
console.log('true', isInt(int));
console.log('true', isInt(str));
console.log('true', 'strict - int', isIntStrict(int));
console.log('false','strict - string', isIntStrict(str));
console.log('false','strict - string', isIntStrict('0x04'));
console.log('true','strict - string', isIntStrict(0x04));
I assume that for your purposes #elclanrs' answer is all you need here, and is the simplest and most straightforward, but just for completeness and dubious laughs, I'm pretty sure that the following would also do what you're looking for:
function isAnIntOrExtra(v) {
if (parseInt(+v) === +v && v !== '') {
return parseInt(+v);
}
else if (v === 'extra') {
return v;
}
else {
return false;
}
}
Fiddle here
These should all pass and return an integer in decimal notation:
'387' returns 387
'-4' returns -4
'0' returns 0
'2.4e3' returns 2400
'0xf4' returns 244
while these should all fail:
'4.5' returns false
'2.4e-3' returns false
'0xgc' returns false
'' returns false
'seven' returns false
And the magic-word 'extra' returns 'extra'
Of course, it'll "fail" miserably with values like '1,345', and will probably roll right over octal notation, treating it as though it were decimal notation (depending on the JavaScript engine?), but it could be tweaked to handle those situations as well, but really, you're better off with the regex.

Difference between Boolan(!x) and Boolean(x==0)?

Code-snippet 1:
if ( !x ) { /* do stuff */ }
Code-snippet 2:
if ( x == 0 ) { /* do stuff */ }
For what values of x do these two code-snippets differ?
I am asking because, although I read the chapter on == in the spec, I still find it hard to deal with situations like the above (where it is combined with ToBoolean coercion).
btw, I want to know this just for the sake of knowing it (I want to understand the language), so don't bother telling me about === or asking me what x is.
Update: I corrected the fist snippet. I meant !x.
[] == 0 is true; ![] is false
null == 0 is false; !null is true
NaN == 0 is false; !NaN is true
undefined == 0 is false; !undefined is true
!x will check whether x is "falsy".
x == 0 will check whether x is "equivalent to" 0.
Both of these terms are defined by the Javascript spec.
The following will give you true for the first and false for the second snippet:
NaN
null
undefined
And these will give you false for the first and true for the second snippet:
[]
"0" and any other string that converts to 0 using Number(x) such as "00", "000", "+0", and "-0" (which I will now call "noughty strings")
an array containing a single element that is 0, null, undefined or an empty or noughty string.
For everything else you'll get the same result for both snippets, although there may be one or two more cases I haven't thought of.
Here's an interesting one with regard to a non-empty String that has only space characters:
!!" "; // true
" " == true; // false
This is because when you do a == comparison, and one of the values being compared is a number or a boolean, an attempt is made to convert the other value to a number.
The reason you get the different result is that a string with only space characters converts to the number 0 (or falsey), while a string with only spaces converted to boolean via !! is seen as a non-empty string, and therefore true.
So:
var x = " ";
alert( !x ); // false
alert( x == 0 ); // true
EDIT:
Probably the key thing to remember is that when comparing a number or boolean to a non number type, == uses toNumber conversion if possible, while ! uses toBoolean conversion. They're not always the same.
It is easy to see the result of the toBoolean conversion using !!. As in:
alert( !![] ); // true
But you can't really see the result of the toNumber conversion when using ==.
You can, however, use the unary + to see the result of a toNumber conversion. As in:
alert( +[] ); // 0
I'm pretty sure that what happens in the case of an Array, is that it first gets a toString call. Therefore:
// ---------------------toString result-------toNumber result (from string)
alert( +[] ); // "" 0
alert( +[""] ); // "" 0
alert( +[" "] ); // " " 0
alert( +[0] ); // "0" 0
alert( +["0"] ); // "0" 0
alert( +["3"] ); // "3" 3
alert( +[3,4] ); // "3,4" NaN
Short answer: the two are almost always the same but not 100% the same.
An example would be (!'0') which is false whereas ('0' == 0) is true
Details:
From: http://www.joeyjavas.com/2007/08/04/javascript-true-false-checking-for-boolean-values/
Checking if a value is true or false is simple in JavaScript. All values evaluate to true, except for:
0
-0
null
undefined
NaN
empty string
false
Therefore, (!x) will be true for all of the above values of x and only those.
As for (x == 0), it will be true for any value of x which - when converted according to "==" conversion rules - is converted to 0 when compared to a number (for example, Boolean false value). Other examples that compare true to ==0 are objects which generate 0 from their valueOf() methods, or a string '0', or an empty Array ([])
The first test will succeed when x is non-zero, or evaluates to an object (as opposed to null or undefined), or is a non-empty string. So if x is 0 then the condition fails, but if it is "0" then it succeeds.
The second test will succeed when x is convertible to 0. This means it must not be null, undefined, or an object to pass this test. And it may be "0" or "".
In other words, these conditionals are not opposites. The value "0" will pass both tests, for example.
Code Snippet 1 will execute if x is "falsy" value. In Javascript, this means 0, -0, null, undefined, NaN, "", or false. Code Snippet 2, however, will only execute if x is zero. Unlike the first condition, this does not include other "falsy" values.
The difference between the two is that
if ( x ) { ... }
Tests whether x is "truthy"
Whereas
if ( x == 0 ) { ... }
Does type coercion between x and 0.
I presume you mean something like
if (x == 0) vs if (!x)
The main difference is type coercion of x to a number vs checking if x is falsy.
Clearly NaN itself will never equal 0 since its not a number. undefined will also coerce to NaN so that is not caught by == 0 I can't give a good explanation why null is not caught by 0 since Number(null) == 0
After some lookups, have to change my awnser.
There's no simple logic, implicit equality operations follows an algorithm.
http://interglacial.com/javascript_spec/a-11.html#a-11.9.3
I can't sum it up better then what the algoritm describes, it would just get more confusing.
So it's (!x) is equivalent to (typeof x === false) aka (not true)
And (x == 0) gets compared by algorithm.

Categories