What's the cleanest, most effective way to validate decimal numbers in JavaScript?
Bonus points for:
- Clarity. Solution should be clean and simple.
- Cross-platform.
Test cases:
01. IsNumeric('-1') => true
02. IsNumeric('-1.5') => true
03. IsNumeric('0') => true
04. IsNumeric('0.42') => true
05. IsNumeric('.42') => true
06. IsNumeric('99,999') => false
07. IsNumeric('0x89f') => false
08. IsNumeric('#abcdef') => false
09. IsNumeric('1.2.3') => false
10. IsNumeric('') => false
11. IsNumeric('blah') => false
knockoutJs Inbuild library validation functions
By extending it the field get validated
1) number
self.number = ko.observable(numberValue)
.extend({ number: true});TestCase
2) digit
self.number = ko.observable(numberValue)
.extend({ digit: true});TestCase
3) min and max
self.number = ko.observable(numberValue)
.extend({ min: 5}).extend({ max: 10});This field accept value between 5 and 10 only
TestCase
Arrrgh! Don't listen to the regular expression answers. RegEx is icky for this, and I'm not talking just performance. It's so easy to make subtle, impossible to spot mistakes with your regular expression.
If you can't use
isNaN()
, this should work much better:Here's how it works:
The
(input - 0)
expression forces JavaScript to do type coercion on your input value; it must first be interpreted as a number for the subtraction operation. If that conversion to a number fails, the expression will result inNaN
. This numeric result is then compared to the original value you passed in. Since the left hand side is now numeric, type coercion is again used. Now that the input from both sides was coerced to the same type from the same original value, you would think they should always be the same (always true). However, there's a special rule that saysNaN
is never equal toNaN
, and so a value that can't be converted to a number (and only values that cannot be converted to numbers) will result in false.The check on the length is for a special case involving empty strings. Also note that it falls down on your 0x89f test, but that's because in many environments that's an okay way to define a number literal. If you want to catch that specific scenario you could add an additional check. Even better, if that's your reason for not using
isNaN()
then just wrap your own function aroundisNaN()
that can also do the additional check.In summary, if you want to know if a value can be converted to a number, actually try to convert it to a number.
I went back and did some research for why a whitespace string did not have the expected output, and I think I get it now: an empty string is coerced to
0
rather thanNaN
. Simply trimming the string before the length check will handle this case.Running the unit tests against the new code and it only fails on the infinity and boolean literals, and the only time that should be a problem is if you're generating code (really, who would type in a literal and check if it's numeric? You should know), and that would be some strange code to generate.
But, again, the only reason ever to use this is if for some reason you have to avoid isNaN().
An integer value can be verified by:
This way is easier and faster! All tests are checked!
Use the function
isNaN
. I believe if you test for!isNaN(yourstringhere)
it works fine for any of these situations.didn't work for me. When I put in an alert and tested,
input.length
wasundefined
. I think there is no property to check integer length. So what I did wasIt worked fine.
@CMS' answer: Your snippet failed on whitespace cases on my machine using nodejs. So I combined it with @joel's answer to the following:
I unittested it with those cases that are floats:
and those cases that are no floats (including empty whitespaces and objects / arrays):
Everything works as expected here. Maybe this helps.
Full source code for this can be found here.