在JavaScript中验证十进制数字最干净、最有效的方法是什么?

奖励积分:

清晰解决方案应干净简单。跨平台。

测试用例:

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

当前回答

我意识到最初的问题没有提到jQuery,但如果您确实使用jQuery,您可以这样做:

$.isNumeric(val)

易于理解的

https://api.jquery.com/jQuery.isNumeric/(截至jQuery 1.7)

其他回答

我认为parseFloat函数可以完成这里的所有工作。下面的函数通过了此页面上的所有测试,包括isNumeric(Infinity)==true:

function isNumeric(n) {

    return parseFloat(n) == n;
}

我运行了下面的程序,它通过了所有测试用例。。。

它使用了parseFloat和Number处理其输入的不同方式。。。

function IsNumeric(_in) {
    return (parseFloat(_in) === Number(_in) && Number(_in) !== NaN);
}

以下方法在许多情况下似乎都很有效:

function isNumeric(num) {
    return (num > 0 || num === 0 || num === '0' || num < 0) && num !== true && isFinite(num);
}

这是建立在这个答案之上的(也是这个答案的基础):https://stackoverflow.com/a/1561597/1985601

被接受的答案没有通过你的7号考试,我想这是因为你改变了主意。所以这是对公认答案的回应,我对此有异议。

在一些项目中,我需要验证一些数据,并尽可能确定它是可以用于数学运算的javascript数值。

jQuery和其他一些javascript库已经包含了这样一个函数,通常称为isNumeric。在stackoverflow上也有一篇文章被广泛接受作为答案,这与前面提到的库所使用的一般例程相同。

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

首先,如果参数是长度为1的数组,并且单个元素的类型被上述逻辑视为数字,则上述代码将返回true。在我看来,如果它是一个数组,那么它就不是数字。

为了缓解这个问题,我从逻辑中添加了一个对折扣数组的检查

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

当然,您也可以使用Array.isArray、jquery$.isArray或原型Object.isArra,而不是Object.protype.toString.call(n)!=='[object数组]'

我的第二个问题是,负十六进制整数文本字符串(“-0xA”->-10)没有被计算为数字。但是,正十六进制整数文本字符串(“0xA”->10)被视为数字。我需要两者都是有效的数字。

然后我修改了逻辑以将其考虑在内。

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

如果您担心每次调用函数时都会创建正则表达式,那么可以在闭包中重写它,如下所示

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

然后,我采用了CMS+30测试用例,并在jsfiddle上克隆了测试,并添加了额外的测试用例和上述解决方案。

它可能不会取代广泛接受/使用的答案,但如果这是您期望的isNumeric函数的结果,那么希望这会有所帮助。

编辑:正如Bergi所指出的,还有其他可能的对象可以被视为数字对象,最好将其列入白名单,而不是列入黑名单。考虑到这一点,我将增加标准。

我希望我的isNumeric函数只考虑数字或字符串

考虑到这一点,最好使用

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(/^-/, ''));
}

测试解决方案

var testHelper=函数(){var testSuite=函数(){test(“Integer Literals”,函数(){ok(isNumber(“-10”),“负整数字符串”);ok(isNumber(“0”),“零字符串”);ok(isNumber(“5”),“正整数字符串”);ok(isNumber(-16),“负整数”);ok(isNumber(0),“零整数”);ok(isNumber(32),“正整数”);ok(isNumber(“040”),“八进制整数字符串”);ok(isNumber(0144),“八进制整数文字”);ok(isNumber(“-040”),“负八进制整数字符串”);ok(isNumber(-0144),“负八进制整数文字”);ok(isNumber(“0xFF”),“十六进制整数字符串”);ok(isNumber(0xFFF),“十六进制整数文字”);ok(isNumber(“-0xFF”),“负十六进制整数字符串”);ok(isNumber(-0xFFF),“负十六进制整数文字”);});测试(“Foating Point Literals”,函数(){ok(isNumber(“-1.6”),“负浮点字符串”);ok(isNumber(“4.536”),“正浮点字符串”);ok(isNumber(-2.6),“负浮点数”);ok(isNumber(3.1415),“正浮点数”);ok(isNumber(8e5),“指数表示法”);ok(isNumber(“123e-2”),“指数符号字符串”);});测试(“非数值”,函数(){equals(isNumber(“”),false,“空字符串”);equals(isNumber(“”),false,“空白字符串”);equals(isNumber(“\t\t”),false,“制表符字符串”);等于(isNumber(“abcdefghijklm123467890”),false,“字母数字字符串”);等于(isNumber(“xabcdefx”),false,“非数字字符串”);equals(isNumber(true),false,“Boolean true literal”);equals(isNumber(false),false,“Boolean false literal”);等于(isNumber(“bcfed5.2”),false,“前面有非数字字符的数字”);等于(isNumber(“7.2acdgs”),false,“带尾随非数字字符的数字”);equals(isNumber(undefined),false,“未定义值”);equals(isNumber(null),false,“null值”);等于(isNumber(NaN),false,“NaN值”);equals(isNumber(无限),false,“无限基元”);等于(isNumber(Number.POSITIVE_INFINITY),false,“正无穷大”);等于(isNumber(Number.NEGATIVE_INFINITY),false,“负无穷大”);等于(isNumber(新日期(2009,1,1)),false,“日期对象”);equals(isNumber(new Object()),false,“空对象”);equals(isNumber(function(){}),false,“函数的实例”);equals(isNumber([]),false,“空数组”);equals(isNumber([“-10”]),false,“数组负整数字符串”);equals(isNumber([“0”]),false,“Array Zero string”);equals(isNumber([“5”]),false,“数组正整数字符串”);等于(isNumber([-16]),false,“数组负整数”);equals(isNumber([0]),false,“Array Zero integer number”);equals(isNumber([32]),false,“数组正整数”);equals(isNumber([“040”]),false,“数组八进制整数字符串”);equals(isNumber([0144]),false,“数组八进制整数文字”);equals(isNumber([“-040”]),false,“数组负八进制整数字符串”);equals(isNumber([-0144]),false,“数组负八进制整数文字”);equals(isNumber([“0xFF”]),false,“数组十六进制整数字符串”);equals(isNumber([0xFFF]),false,“数组十六进制整数文字”);equals(isNumber([“-0xFF”]),false,“数组负十六进制整数字符串”);等于(isNumber([-0xFFF]),false,“数组负十六进制整数文字”);equals(isNumber([1,2]),false,“具有1个以上正整数的数组”);equals(isNumber([-1,-2]),false,“具有1个以上负整数的数组”);});}var函数ToTest=[函数(n){回来isNaN(parseFloat(n))&&isFinite(n);},函数(n){回来isNaN(n)&&!isNaN(parseFloat(n));},函数(n){回来isNaN((n));},函数(n){回来isNaN(parseFloat(n));},函数(n){返回类型(n)!=“布尔”&&!isNaN(n);},函数(n){return parseFloat(n)==数字(n);},函数(n){return parseInt(n)==数字(n);},函数(n){回来isNaN(数字(字符串(n)));},函数(n){回来isNaN(+(“”+n));},函数(n){返回(+n)==n;},函数(n){返回n&&/^-?\d+(\.\d+)?$/。测试(n+“”);},函数(n){return isFinite(数字(字符串(n)));},函数(n){return isFinite(字符串(n));},函数(n){回来isNaN(n)&&!isNaN(parseFloat(n))&&isFinite(n);},函数(n){返回parseFloat(n)==n;},函数(n){return(n-0)==n&&n长度>0;},函数(n){返回类型n==“number”&&isFinite(n);},函数(n){回来Array.isArray(n)&&!isNaN(parseFloat(n))&&isFinite(n.toString().replace(/^-/,“”));}];//检查函数ToTest数组,提取每个函数的返回语句//并填充toTest select元素。var fillToTestSelect=函数(){对于(var i=0;i<functionsToTest.length;i++){var f=函数ToTest[i].toString();var option=/[\s\s]*return([\s\s]*);/。执行(f)[1];$(“#toTest”).append('<option value=“'+i+'”>'+(i+1)+'.'+option+'</option>');}}var performTest=函数(函数编号){reset();//重置上一测试$(“#tests”).html(“”)//清洁测试结果isNumber=函数ToTest[函数编号];//用要测试的函数重写isNumber全局函数testSuite();//运行测试//获取测试结果var totalFail=0;v

我用这种方法检查变量是否为数字:

v * 1 == v