在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

当前回答

啊!不要听正则表达式的答案。RegEx很讨厌这个,我说的不仅仅是性能。用正则表达式很容易发现细微的、不可能发现的错误。

如果您不能使用isNaN(),这应该会更好:

function IsNumeric(input)
{
    return (input - 0) == input && (''+input).trim().length > 0;
}

以下是它的工作原理:

(input-0)表达式强制JavaScript对输入值执行类型强制;它必须首先被解释为减法运算的数字。如果转换为数字失败,表达式将生成NaN。然后将此数字结果与传入的原始值进行比较。由于左侧现在是数字,因此再次使用类型强制。既然来自双方的输入被强制为来自相同原始值的相同类型,那么您会认为它们应该总是相同的(总是正确的)。然而,有一条特殊规则规定NaN永远不等于NaN,因此不能转换为数字的值(只有不能转换为数值的值)将导致错误。

长度检查用于涉及空字符串的特殊情况。还要注意,这取决于0x89f测试,但这是因为在许多环境中,这是定义数字文字的好方法。如果您想捕捉特定场景,可以添加额外的检查。更好的是,如果这是您不使用isNaN()的原因,那么只需将您自己的函数包装在isNaN)周围,这也可以进行额外的检查。

总之,如果您想知道某个值是否可以转换为数字,请尝试将其转换为数字。


我回去研究了为什么空白字符串没有预期的输出,我想我现在明白了:空字符串被强制为0而不是NaN。只需在长度检查之前修剪字符串即可处理这种情况。

针对新代码运行单元测试,它只会在无穷大和布尔文本上失败,唯一可能出现问题的是,如果你正在生成代码(真的,谁会键入文本并检查它是否为数字?你应该知道),那将是一些奇怪的代码。

但是,再次强调,使用此选项的唯一原因是,如果出于某种原因,您必须避免使用isNaN()。

其他回答

这种方式似乎很有效:

function IsNumeric(input){
    var RE = /^-{0,1}\d*\.{0,1}\d+$/;
    return (RE.test(input));
}

在一行中:

const IsNumeric = (num) => /^-{0,1}\d*\.{0,1}\d+$/.test(num);

要测试它:

常量IsNumeric=(num)=>/^-{0,1}\d*\。{0,1}\d+$/.test(num);函数TestIsNumeric(){var结果=“”results+=(IsNumeric('-1')?“通过”:“失败”)+“:IsNumeric('-1')=>true\n”;结果+=(IsNumeric('-1.5')?“通过”:“失败”)+“:IsNumeric('-1.5')=>true\n”;结果+=(IsNumeric(“0”)?“通过”:“失败”)+“:IsNumeric('0')=>true\n”;结果+=(IsNumeric(“0.42”)?“通过”:“失败”)+“:IsNumeric('0.42')=>true\n”;results+=(IsNumeric('.42')?“通过”:“失败”)+“:IsNumeric('.42')=>true\n”;results+=(!IsNumeric('99999')?“通过”:“失败”)+“:IsNumeric(‘99999’)=>false \n”;results+=(!IsNumeric('0x89f')?“通过”:“失败”)+“:IsNumeric('0x89f')=>false \n”;results+=(!IsNumeric('#abcdef')?“通过”:“失败”)+“:IsNumeric('#abcdef')=>false \n”;results+=(!IsNumeric('1.2.3')?“通过”:“失败”)+“:IsNumeric('1.2.3')=>false \n”;results+=(!IsNumeric(“”)?“通过”:“失败”)+“:IsNumeric(“”)=>false \n”;results+=(!IsNumeric('barh')?“通过”:“失败”)+“:IsNumeric('barh')=>false \n”;返回结果;}console.log(TestIsNumeric());.作为控制台包装{最大高度:100%!重要;顶部:0;}

我从那里借来的正则表达式http://www.codetoad.com/javascript/isnumeric.asp.说明:

/^ match beginning of string
-{0,1} optional negative sign
\d* optional digits
\.{0,1} optional decimal point
\d+ at least one digit
$/ match end of string
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

这也适用于0x23类型编号。

这里有一个稍微改进的版本(可能是最快的版本),我用它代替了jQuery的变体,我真的不知道他们为什么不使用这个:

function isNumeric(val) {
    return !isNaN(+val) && isFinite(val);
}

jQuery版本的缺点是,如果您传递一个带前导数字和尾随字母(如“123abc”)的字符串,parseFloat|parseInt将提取数字分数并返回123,但第二个保护isFinite无论如何都会失败。使用一元+运算符,它将在第一个守卫中死亡,因为+为此类混合体抛出NaN:)虽然有点表现,但我认为语义上有了坚实的收获。

我找到了简单的解决方案,可能不是最好的,但效果很好:)

所以,我接下来要做的是,将字符串解析为Int,并检查新变量的长度大小(现在是Int类型)是否和原始字符串变量的长度相同。从逻辑上讲,如果大小相同,则意味着字符串被完全解析为int,并且只有当字符串仅由数字“构成”时,这才是可能的。

var val=1+$(e).val()+'';
var n=parseInt(val)+'';
if(val.length == n.length )alert('Is int');

您可以很容易地将该代码放在函数中,如果int,则使用return true代替alert。记住,如果您在字符串中使用点或逗号,您将检查它是否仍然为false,因为您正在解析为int。

注意:在e.val上添加1+,因此不会删除起始零。

我的解决方案,

function isNumeric(input) {
    var number = /^\-{0,1}(?:[0-9]+){0,1}(?:\.[0-9]+){0,1}$/i;
    var regex = RegExp(number);
    return regex.test(input) && input.length>0;
}

它似乎在任何情况下都有效,但我可能错了。