在 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(),这应该会更好:
isNaN()
function IsNumeric(input) { return (input - 0) == input && (''+input).trim().length > 0; }
以下是它的工作原理:
该(input - 0)表达式强制 JavaScript 对您的输入值进行类型强制;它必须首先被解释为减法运算的数字。如果转换为数字失败,则表达式将导致NaN. 然后将此数字结果与您传入的原始值进行比较。由于左侧现在是数字,因此再次使用类型强制。既然双方的输入都从相同的原始值强制转换为相同的类型,您会认为它们应该始终相同(始终为真)。但是,有一条特殊规则说NaN永远不等于NaN,因此不能转换为数字的值(并且只有不能转换为数字的值)将导致 false。
(input - 0)
NaN
检查长度是针对涉及空字符串的特殊情况。另请注意,它落在您的 0x89f 测试中,但这是因为在许多环境中,这是定义数字文字的好方法。如果您想捕捉该特定情况,您可以添加额外的检查。更好的是,如果这是您不使用的原因,isNaN()那么只需将您自己的函数包装起来isNaN(),也可以进行额外的检查。
综上所述,*如果你想知道一个值是否可以转换为数字,实际上尝试将其转换为数字。*
我回去做了一些研究,为什么空白字符串没有预期的输出,我想我现在明白了:一个空字符串被强制转换为0而不是NaN. 只需在长度检查之前修剪字符串即可处理这种情况。
0
对新代码运行单元测试,它只会在无穷大和布尔文字上失败,唯一应该成为问题的时间是如果你正在生成代码(真的,谁会输入文字并检查它是否是数字?你应该知道),这将是一些奇怪的代码生成。
但是,再次使用它的唯一原因是,如果由于某种原因您必须避免使用 isNaN()。
楼上的答案非常接近,但在以下情况下会失败:
// 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函数,以找出一个变量是否包含一个数值,无论它的类型如何,它可能是一个String包含一个数值(我还必须考虑指数符号等),一个Number对象,几乎任何东西都可以传递给那个函数,我不能做任何类型假设,照顾类型强制(例如,+true == 1;但true不应该被视为"numeric")。
IsNumeric
String
Number
+true == 1;
true
"numeric"
我认为值得分享对众多功能实现进行的这组+30 单元测试,并分享通过我所有测试的单元测试:
function isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); }
由于强制转换为数字,PS isNaN和isFinite具有令人困惑的行为。在 ES6 中,Number.isNaN和Number.isFinite将解决这些问题。使用它们时请记住这一点。
更新: 这是 jQuery 现在的做法(2.2-stable):
isNumeric: function(obj) { var realStringObj = obj && obj.toString(); return !jQuery.isArray(obj) && (realStringObj - parseFloat(realStringObj) + 1) >= 0; }
更新: 角 4.3:
export function isNumeric(value: any): boolean { return !isNaN(value - parseFloat(value)); }