在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
可以使用类型检查库,如https://github.com/arasatasaygin/is.js或者从那里提取一个检查片段(https://github.com/arasatasaygin/is.js/blob/master/is.js#L131):
is.nan = function(value) { // NaN is number :)
return value !== value;
};
// is a given value number?
is.number = function(value) {
return !is.nan(value) && Object.prototype.toString.call(value) === '[object Number]';
};
通常,如果您需要它来验证参数类型(在函数调用的入口点),您可以使用符合JSDOC的契约(https://www.npmjs.com/package/bycontract):
/**
* This is JSDOC syntax
* @param {number|string} sum
* @param {Object.<string, string>} payload
* @param {function} cb
*/
function foo( sum, payload, cb ) {
// Test if the contract is respected at entry point
byContract( arguments, [ "number|string", "Object.<string, string>", "function" ] );
}
// Test it
foo( 100, { foo: "foo" }, function(){}); // ok
foo( 100, { foo: 100 }, function(){}); // exception
我意识到这一点已经得到了多次回答,但以下是一个不错的人选,在某些情况下可能有用。
需要注意的是,它假设‘.42’不是一个数字,‘4.’不是数字,因此应该考虑到这一点。
function isDecimal(x) {
return '' + x === '' + +x;
}
function isInteger(x) {
return '' + x === '' + parseInt(x);
}
isDecimal通过以下测试:
function testIsNumber(f) {
return f('-1') && f('-1.5') && f('0') && f('0.42')
&& !f('.42') && !f('99,999') && !f('0x89f')
&& !f('#abcdef') && !f('1.2.3') && !f('') && !f('blah');
}
这里的想法是,每个数字或整数都有一个“规范”字符串表示,每个非规范表示都应该被拒绝。所以我们将其转换为一个数字并返回,看看结果是否为原始字符串。
这些函数是否对您有用取决于用例。一个特点是不同的字符串表示不同的数字(如果两者都通过isNumber()测试)。
这与例如作为对象属性名称的数字相关。
var obj = {};
obj['4'] = 'canonical 4';
obj['04'] = 'alias of 4';
obj[4]; // prints 'canonical 4' to the console.
啊!不要听正则表达式的答案。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()。
knockoutJs内置库验证函数
通过扩展它,该字段得到验证
1) 编号
self.number=ko.obsobservable(numberValue).exextend({number:true});
测试用例
numberValue = '0.0' --> true
numberValue = '0' --> true
numberValue = '25' --> true
numberValue = '-1' --> true
numberValue = '-3.5' --> true
numberValue = '11.112' --> true
numberValue = '0x89f' --> false
numberValue = '' --> false
numberValue = 'sfsd' --> false
numberValue = 'dg##$' --> false
2) 数字
self.number=ko.obsobservable(numberValue).exextend({digit:true});
测试用例
numberValue = '0' --> true
numberValue = '25' --> true
numberValue = '0.0' --> false
numberValue = '-1' --> false
numberValue = '-3.5' --> false
numberValue = '11.112' --> false
numberValue = '0x89f' --> false
numberValue = '' --> false
numberValue = 'sfsd' --> false
numberValue = 'dg##$' --> false
3) 最小值和最大值
self.number=可观察(numberValue).扩展({min:5}).扩展;
此字段仅接受介于5和10之间的值
测试用例
numberValue = '5' --> true
numberValue = '6' --> true
numberValue = '6.5' --> true
numberValue = '9' --> true
numberValue = '11' --> false
numberValue = '0' --> false
numberValue = '' --> false