问题 如何检查JavaScript编号是否真实有效?


我的代码是:

function isNumber(n){
return typeof n == 'number' && !isNaN(n);
}

window.onload=function(){
var a=0,b=1,c=2.2,d=-3,e=-4.4,f=10/3;
var shouldBeTrue=[a,b,c,d,e,f];

var aa="0",bb="1",cc="2.2",dd="-3",ee="-4.4",ff="10/3";
var shouldBeFalse=[aa,bb,cc,dd,ee,ff];

var aaa,bbb=true,ccc=false,ddd=document.getElementsByTagName('html');
var alsoTheseBeFalse=[aaa,bbb,ccc,ddd,""," ",,null,NaN];

for(var i=0;i<shouldBeTrue.length;i++)
    if(isNumber(shouldBeTrue[i]) != true) alert("x");
for(i=0;i<shouldBeFalse.length;i++)
    if(isNumber(shouldBeFalse[i]) != false) alert("x");
for(i=0;i<alsoTheseBeFalse.length;i++)
    if(isNumber(alsoTheseBeFalse[i]) != false) alert("x");
}

我应该检查什么以确保我的功能在所有方面都是101%完美? (另外,如果你知道更好的功能请告诉我)


1448
2017-12-15 20:04


起源

你希望哪个功能完美?你可以先给你的变量更有意义的名字...... - frenchie
@frenchie:他在谈论这个 isNumber(n) 功能。 - Cᴏʀʏ
有没有检查的数字情况,但我不能让你的功能中断(即:g = 2E30,gg = 0/0) - Brian
@Brian,好0/0 = NaN(我确实检查过),但我对'2E30'的事情感到好奇,因为它返回true。你知道它为什么会返回真实吗?
旁注,在您的测试用例中,您正在使用 != false。这不是必需的,因为你的 isNumber 函数总是返回一个布尔值(true 要么 false)。中 if ( ... ),表达式总是被视为布尔值。 if (isNumber(a) != false) 相当于 if (isNumber(a) == true) 相当于 if (isNumber(a))。 - Rob W


答案:


如果要检查数字是否为实数,还应检查它是否有限:

function isNumber(n){
    return typeof n == 'number' && !isNaN(n) && isFinite(n);
 }

另一种方法(下面的解释):

function isNumber(n){
    return typeof n == 'number' && !isNaN(n - n);
}

更新:验证实数的两个表达式

由于JavaScript数字表示实数,因此相同数字上的减法操作数应产生零值 (附加身份)。超出范围的数字应该(并且将)无效, NaN

1        - 1        = 0    // OK
Infinity - Infinity = NaN  // Expected
NaN      - NaN      = NaN  // Expected
NaN      - Infinity = NaN

16
2017-12-15 20:15



那么,你的代码更大,再做一次操作。我使用它的唯一方法是,如果你告诉我一种方式,我的当前功能会失败而你不会
@TuxedoKnightChess输入以下值: Infinity。它通过了前两个测试,但它不是一个有用的实数: isNumber(Infinity) 为当前函数返回true。 - Rob W
结果会是什么? var n=2E30;?
@TuxedoKnightChess:有一个真正简单的方法可以找到答案。 - RightSaidFred
@TuxedoKnightChess方法略有不同,但结果非常平等。 - Rob W


JS编号可以是以下值之一:

  • 有限数字
  • +Infinity 和 -Infinity
  • NaN

然后还存在可对数字进行强制的非数字值,例如数字对象。您可能想要将它们视为数字。

如果您只想测试有限数字,只需使用即可 Number.isFinite

Number.isFinite(value)

var isNumber = Number.isFinite;
assert('isNumber(1)', true);
assert('isNumber(1.1)', true);
assert('isNumber(+0)', true);
assert('isNumber(-0)', true);
assert('isNumber(-1.1)', true);
assert('isNumber(Math.PI)', true);
assert('isNumber(1e300)', true);
assert('isNumber(+Infinity)', false);
assert('isNumber(-Infinity)', false);
assert('isNumber(NaN)', false);
assert('isNumber(null)', false);
assert('isNumber(undefined)', false);
assert('isNumber(true)', false);
assert('isNumber(false)', false);
assert('isNumber("123")', false);
assert('isNumber("foo")', false);
assert('isNumber(new Number(1))', false);
assert('isNumber([])', false);
assert('isNumber({})', false);
assert('isNumber(function(){})', false);
function assert(code, expected) {
  var result = eval(code);
  console.log('Test ' + (result===expected ? 'pass' : 'FAIL') + ': ', code, ' -> ', result);
}

如果要包含无穷大,请检查类型并排除 NaN

typeof value === "number" && !Number.isNaN(value)

function isNumber(value) {
  return typeof value === "number" && !Number.isNaN(value);
}
assert('isNumber(1)', true);
assert('isNumber(1.1)', true);
assert('isNumber(+0)', true);
assert('isNumber(-0)', true);
assert('isNumber(-1.1)', true);
assert('isNumber(Math.PI)', true);
assert('isNumber(1e300)', true);
assert('isNumber(+Infinity)', true);
assert('isNumber(-Infinity)', true);
assert('isNumber(NaN)', false);
assert('isNumber(null)', false);
assert('isNumber(undefined)', false);
assert('isNumber(true)', false);
assert('isNumber(false)', false);
assert('isNumber("123")', false);
assert('isNumber("foo")', false);
assert('isNumber(new Number(1))', false);
assert('isNumber([])', false);
assert('isNumber({})', false);
assert('isNumber(function(){})', false);
function assert(code, expected) {
  var result = eval(code);
  console.log('Test ' + (result===expected ? 'pass' : 'FAIL') + ': ', code, ' -> ', result);
}

如果要将数字对象视为数字,可以使用它来解开它们

value = Number.valueOf.call(value); // throws if value was not a number object

function isNumber(value) {
  try { value = Number.prototype.valueOf.call(value); } catch(err) { }
  return Number.isFinite(value);
}
assert('isNumber(1)', true);
assert('isNumber(1.1)', true);
assert('isNumber(+0)', true);
assert('isNumber(-0)', true);
assert('isNumber(-1.1)', true);
assert('isNumber(Math.PI)', true);
assert('isNumber(1e300)', true);
assert('isNumber(+Infinity)', false);
assert('isNumber(-Infinity)', false);
assert('isNumber(NaN)', false);
assert('isNumber(null)', false);
assert('isNumber(undefined)', false);
assert('isNumber(true)', false);
assert('isNumber(false)', false);
assert('isNumber("123")', false);
assert('isNumber("foo")', false);
assert('isNumber(new Number(1))', true);
assert('isNumber([])', false);
assert('isNumber({})', false);
assert('isNumber(function(){})', false);
function assert(code, expected) {
  var result = eval(code);
  console.log('Test ' + (result===expected ? 'pass' : 'FAIL') + ': ', code, ' -> ', result);
}

如果要包含对数字具有可强制性的任意值,可以使用一元 + 强迫

value = +value; // throws if value was not number-coercible

还有 isNaN 功能(不要混淆 Number.isNaN),这将首先强制,然后进行比较 NaN。但要注意空白字符串和 null 被胁迫 +0不是 NaN。所以你可能会感兴趣 在JavaScript中验证十进制数 - IsNumeric()


1
2017-09-24 20:52





这取决于你想要的数字。您的代码将Infinity和-Infinity分类为数字。如果你不想那样,用isFinite(n)替换!isNaN(n)。

由于类型检查,您的代码将'42'(字符串文字)分类为不是数字;但我认为那是故意的。


0
2017-12-15 20:16





我使用解析和检查数字的组合..如下所述

function isNumber(inputValue){ return ((parseFloat(inputValue) ==0 || parseFloat(inputValue)) && !isNaN(inputValue)); };

希望这可以帮助


0
2017-07-30 10:23





如果您认为其对象包装器中的数字是一个数字,那么它将失败:

isNumber( new Number(123) )

由于一个downvoter有一些理解麻烦,通过一个简单的测试无法缓解, new Number(123) 将返回 'object' 来自 typeof 测试,因此不会通过。


-1
2017-12-15 20:18



@ down-voter:给出一个理由。请告诉我怎么样 new Number(123) 将通过 isNumber 测试问题。 - RightSaidFred
我没有downvote,但是你的代码只显示了破坏代码的一些例子,而没有提出解决方案。 OP没有问如何打破这个功能,但是如何 提高 功能。 - Rob W