在JavaScript中验证十进制数 - IsNumeric()

10 浏览
0 Comments

在JavaScript中验证十进制数 - IsNumeric()

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

额外加分项:

  1. 清晰易懂。解决方案应干净简单。
  2. 跨平台。

测试用例:

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

admin 更改状态以发布 2023年5月23日
0
0 Comments

啊啊啊!不要听正则表达式的答案。使用正则表达式处理这个问题非常棘手,我说的不仅是性能问题。使用正则表达式非常容易出现微妙的错误,而这些错误又很难被发现。

如果你不能使用 isNaN(),那么下面的方法会更加好用:

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

下面是它的工作原理:

(input - 0) 表达式强制 JavaScript 将你的输入值进行类型转换,为了进行减法操作,输入值必须首先被解释为一个数字。如果转换为数字失败,该表达式的结果将是 NaN。这个数值结果随后会与你传入的原始值进行比较。由于左侧现在是数字的,因此再次使用了类型转换。现在,输入来自两侧都是从同一原始值转换为相同类型的,您可能认为它们应该总是相同的(始终为真)。然而,有一条特殊规则,规定 NaN 永远不等于 NaN,因此一个无法转换为数字的值(仅限无法转换为数字的值)将返回 false。

长度检查是针对空字符串的特殊情况。还要注意的是,它在你的 0x89f 测试中未通过,但这是因为在许多环境中,这种方式定义数字文字是可以接受的。如果您想捕捉该特定情况,您可以添加一个额外的检查。更好的方法是,如果您不使用 isNaN() 的原因是这个,那么只需在 isNaN() 周围封装自己的函数,即可额外执行这个检查。

总之,如果想知道一个值是否可以转换为数字,那就真的试着将其转换为数字。


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

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

但是,再次提醒,唯一的原因就是如果你必须避免isNaN()。

0
0 Comments

@Joel's answer很接近,但在以下情况下会失败:

// Whitespace strings:
IsNumeric(' ')    == true;
IsNumeric('\t\t') == true;
IsNumeric('\n\r') == true;
// Number literals:
IsNumeric(-1)  == false;
IsNumeric(0)   == false;
IsNumeric(1.1) == false;
IsNumeric(8e5) == false;

不久前,我不得不实现一个IsNumeric函数,以查找变量是否包含数字值,不考虑其类型,它可以是包含数字值(我还必须考虑指数表示法等)的StringNumber对象,任何东西都可以传递给该函数,我不能做出任何类型假设,要注意类型转换(例如+true == 1;true不应被视为"numeric")。

我认为值得分享这组+30个单元测试,以验证各种函数实现,也分享通过所有测试的一个函数:

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

附言: isNaNisFinite由于强制转换为数字而具有混淆的行为。在ES6中,Number.isNaNNumber.isFinite会修复这些问题。在使用它们时请牢记这一点。


更新
这是现在jQuery的做法(2.2稳定版)

isNumeric: function(obj) {
    var realStringObj = obj && obj.toString();
    return !jQuery.isArray(obj) && (realStringObj - parseFloat(realStringObj) + 1) >= 0;
}

更新
Angular 4.3

export function isNumeric(value: any): boolean {
    return !isNaN(value - parseFloat(value));
}

0