An improved isNumeric() function?

孤街醉人 提交于 2019-12-03 05:28:06

问题


During some projects I have needed to validate some data and be as certain as possible that it is javascript numerical value that can be used in mathematical operations.

jQuery, and some other javascript libraries already include such a function, usually called isNumeric. There is also a post on stackoverflow that has been widely accepted as the answer, the same general routine that the fore mentioned libraries are using.

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

Being my first post, I was unable to reply in that thread. The issue that I had with the accepted post was that there appear to be some corner cases that affected some work that I was doing, and so I made some changes to try and cover the issue I was having.

First, the code above would return true if the argument was an array of length 1, and that single element was of a type deemed as numeric by the above logic. In my opinion, if it's an array then its not numeric.

To alleviate this problem, I added a check to discount arrays from the logic

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n);
}

Of course, you could also use Array.isArray instead of Object.prototype.toString.call(n) !== '[object Array]'

EDIT: I've changed the code to reflect a generic test for array, or you could use jquery $.isArray or prototypes Object.isArray

My second issue was that Negative Hexadecimal integer literal strings ("-0xA" -> -10) were not being counted as numeric. However, Positive Hexadecimal integer literal strings ("0xA" -> 10) wrere treated as numeric. I needed both to be valid numeric.

I then modified the logic to take this into account.

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

If you are worried about the creation of the regex each time the function is called then you could rewrite it within a closure, something like this

isNumber = (function () {
  var rx = /^-/;

  return function (n) {
      return Object.prototype.toString.call(n) !== '[object Array]' && !isNaN(parseFloat(n)) && isFinite(n.toString().replace(rx, ''));
  };
}());

I then took CMSs +30 test cases and cloned the testing on jsfiddle added my extra test cases and my above described solution.

Everything appears to be working as expected and I haven't experienced any issues. Are there any issues, code or theoretical, that you can see?

It may not replace the widely accepted/used answer but if this is what you are expecting as results from your isNumeric function then hopefully this will be of some help.

EDIT: As pointed out by Bergi, there are other possible objects that could be considered numeric and it would be better to whitelist than blacklist. With this in mind I would add to the criteria.

I want my isNumeric function to consider only Numbers or Strings

With this in mind, it would be better to use

function isNumber(n) {
  return (Object.prototype.toString.call(n) === '[object Number]' || Object.prototype.toString.call(n) === '[object String]') &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

This has been added as test 22


回答1:


In my opinion, if it's an array then its not numeric. To alleviate this problem, I added a check to discount arrays from the logic

You can have that problem with any other object as well, for example {toString:function(){return "1.2";}}. Which objects would you think were numeric? Number objects? None?

Instead of trying to blacklist some things that fail your test, you should explicitly whitelist the things you want to be numeric. What is your function supposed to get, primitive strings and numbers? Then test exactly for them:

(typeof n == "string" || typeof n == "number")



回答2:


If it's OK for you to use regular expressions, this might do the trick:

function (n) 
    { 
    return (Object.prototype.toString.call(n) === '[object Number]' ||
            Object.prototype.toString.call(n) === '[object String]') && 
           (typeof(n) != 'undefined')  &&  (n!=null) && 
           (/^-?\d+((.\d)?\d*(e[-]?\d)?(\d)*)$/.test(n.toString()) ||
           /^-?0x[0-9A-F]+$/.test(n.toString()));
    }

edit: Fixed problem with hex numbers




回答3:


If AMD sounds good to you, have a look at mout's isNumber().




回答4:


function isNumber(value){return typeof value == 'number';}



回答5:


How about:

function isNumber(value) {
  value = Number(value);
  return typeof value === 'number' && !isNaN(value) && isFinite(value);
}



回答6:


isNaN function used to check the value is a numeric or not. If the values is numeric its return true else returned false.

code:

 <script>

         function IsNumeric(val) {

              if (isNaN(parseFloat(val))) {

                 return false;

          }

          return true

  }


  bool IsNumeric(string);


</script>



回答7:


function isNumber(value){
    return !isNaN(parseFloat(value)) && 
        isFinite(value.toString().replace(/^-/, '')) && 
        typeof value !== 'object';

}

or :

function isNumber(value){
    return !Array.isArray(value) && !isNaN(parseFloat(value)) && 
        isFinite(value.toString().replace(/^-/, '')) && 
        Object.prototype.toString.call(value) !== '[object Object]';
}


来源:https://stackoverflow.com/questions/15042989/an-improved-isnumeric-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!