关于验证:(内置)JavaScript方式检查字符串是否为有效数字

(Built-in) way in JavaScript to check if a string is a valid number

我希望在同一个概念空间中有什么东西与旧的vb6 IsNumeric()函数相同?


要检查变量(包括字符串)是否是数字,请检查它是否不是数字:

不管变量内容是字符串还是数字,这都有效。

1
isNaN(num)         // returns true if the variable does NOT contain a valid number

实例

1
2
3
4
5
isNaN(123)         // false
isNaN('123')       // false
isNaN('1e10000')   // false (This translates to Infinity, which is a number)
isNaN('foo')       // true
isNaN('10px')      // true

当然,如果你需要的话,你可以否定这一点。例如,要实现IsNumeric示例,您给出了:

1
2
3
function isNumeric(num){
  return !isNaN(num)
}

要将包含数字的字符串转换为数字:

只有当字符串只包含数字字符时才有效,否则返回NaN

1
2
+num               // returns the numeric value of the string, or NaN
                   // if the string isn't purely numeric characters

实例

1
2
3
4
5
6
7
+'12'              // 12
+'12.'             // 12
+'12..'            // Nan
+'.12'             // 0.12
+'..12'            // Nan
+'foo'             // NaN
+'12px'            // NaN

将字符串松散地转换为数字

用于将"12px"转换为12,例如:

1
2
parseInt(num)      // extracts a numeric value from the
                   // start of the string, or NaN.

实例

1
2
3
4
5
parseInt('12')     // 12
parseInt('aaa')    // NaN
parseInt('12px')   // 12
parseInt('foo2')   // NaN      These last two may be different
parseInt('12a5')   // 12       from what you expected to see.

漂浮物

记住,与+num不同,parseInt(顾名思义)将通过切掉小数点后的所有内容,将浮点转换为整数(如果您希望使用parseInt(),因为这种行为,您最好使用其他方法):

1
2
3
+'12.345'          // 12.345
parseInt(12.345)   // 12
parseInt('12.345') // 12

空字符串

空字符串可能有点违反直觉。+num将空字符串转换为零,isNaN()假定相同:

1
2
+''                // 0
isNaN('')          // false

parseInt()不同意:

1
parseInt('')       // NaN


你可以走Regexp的路:

1
2
3
4
5
6
7
8
9
var num ="987238";

if(num.match(/^-{0,1}\d+$/)){
  //valid integer (positive or negative)
}else if(num.match(/^\d+\.\d+$/)){
  //valid float
}else{
  //not valid number
}


如果你只是想检查一个字符串是否是一个整数(没有小数点),那么regex是一个很好的方法。其他方法,如isNaN,对于如此简单的事情来说过于复杂。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function isNumeric(value) {
    return /^-{0,1}\d+$/.test(value);
}

console.log(isNumeric('abcd'));         // false
console.log(isNumeric('123a'));         // false
console.log(isNumeric('1'));            // true
console.log(isNumeric('1234567890'));   // true
console.log(isNumeric('-23'));          // true
console.log(isNumeric(1234));           // true
console.log(isNumeric('123.4'));        // false
console.log(isNumeric(''));             // false
console.log(isNumeric(undefined));      // false
console.log(isNumeric(null));           // false

要只允许正整数,请使用此选项:

1
2
3
4
5
6
function isNumeric(value) {
    return /^\d+$/.test(value);
}

console.log(isNumeric('123'));          // true
console.log(isNumeric('-23'));          // false


如果你真的想确保一个字符串只包含一个数字,任何数字(整数或浮点),以及一个确切的数字,你就不能自己使用EDCOX1,2,EDCX1,3,EDCOX1,4,或者EDCOX1,5。请注意,当EDOCX1引用4返回时,EDCOX1的5实际上是返回EDCOX1×7;EDCX1 9返回时,EDOCX1 OR 10表示,因此,我将将其排除在讨论的其余部分。

EDCOX1的3个问题是,如果字符串包含任何数字,即使字符串不包含和仅包含一个数字,它也会返回一个数字:

1
2
3
parseFloat("2016-12-31")  // returns 2016
parseFloat("1-1") // return 1
parseFloat("1.2.3") // returns 1.2

Number()的问题是,如果传递的值不是数字,它将返回一个数字!

1
2
3
4
5
Number("") // returns 0
Number("") // returns 0
Number(" \u00A0   \t

"
) // returns 0

滚动您自己的regex的问题是,除非您创建精确的regex来匹配一个浮点数,因为javascript识别它,否则您将错过案例或识别不应该出现的案例。即使您可以滚动自己的regex,为什么?有更简单的内置方式。

然而,事实证明,Number()isNaN()parseFloat()不应该返回数字的情况下都是正确的,反之亦然。因此,要查明字符串是否确实是且仅是数字,请调用这两个函数并查看它们是否都返回真:

1
2
3
4
5
function isNumber(str) {
  if (typeof str !="string") return false // we only process strings!
  // could also coerce to string: str =""+str
  return !isNaN(str) && !isNaN(parseFloat(str))
}


尝试isnan函数:

The isNaN() function determines whether a value is an illegal number (Not-a-Number).

This function returns true if the value equates to NaN. Otherwise it returns false.

This function is different from the Number specific Number.isNaN() method.

  The global isNaN() function, converts the tested value to a Number, then tests it.

Number.isNan() does not convert the values to a Number, and will not return true for any value that is not of the type Number...


旧问题,但在给出的答案中有几点遗漏。

科学记数法。

!isNaN('1e+30')true,但在大多数人询问数字的情况下,他们不想匹配EDCX1〔10〕之类的东西。

大浮动数可能表现怪异

观察(使用No.js):

1
2
3
4
5
6
7
8
9
10
11
12
13
> var s = Array(16 + 1).join('9')
undefined
> s.length
16
> s
'9999999999999999'
> !isNaN(s)
true
> Number(s)
10000000000000000
> String(Number(s)) === s
false
>

另一方面:

1
2
3
4
5
6
7
8
9
> var s = Array(16 + 1).join('1')
undefined
> String(Number(s)) === s
true
> var s = Array(15 + 1).join('9')
undefined
> String(Number(s)) === s
true
>

因此,如果期望EDCOX1为11,那么最好将字符串限制在15位(省略前导零)。

无穷

1
2
3
4
5
6
7
> typeof Infinity
'number'
> !isNaN('Infinity')
true
> isFinite('Infinity')
false
>

考虑到所有这些,检查给定的字符串是否是满足以下所有条件的数字:

  • 非科学符号
  • 可预测转换为NumberString
  • 有限的

这不是一件容易的事。下面是一个简单的版本:

1
2
3
4
5
6
7
  function isNonScientificNumberString(o) {
    if (!o || typeof o !== 'string') {
      // Should not be given anything but strings.
      return false;
    }
    return o.length <= 15 && o.indexOf('e+') < 0 && o.indexOf('E+') < 0 && !isNaN(o) && isFinite(o);
  }

然而,即使是这一个也远远不够完整。前导零不在这里处理,但它们会进行螺旋长度测试。


这个问题的公认答案有相当多的缺陷(如其他几个用户所强调的)。这是用JavaScript处理它的最简单且经验证的方法之一:

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

下面是一些好的测试用例:

1
2
3
4
5
6
7
8
9
10
console.log(isNumeric(12345678912345678912)); // true
console.log(isNumeric('2 '));                 // true
console.log(isNumeric('-32.2 '));             // true
console.log(isNumeric(-32.2));                // true
console.log(isNumeric(undefined));            // false

// the accepted answer fails at these tests:
console.log(isNumeric(''));                   // false
console.log(isNumeric(null));                 // false
console.log(isNumeric([]));                   // false

也许有一两个人遇到这个问题,他们需要比平时更严格的检查(就像我一样)。在这种情况下,这可能有用:

1
2
3
if(str === String(Number(str))) {
  // it's a"perfectly formatted" number
}

当心!这将拒绝诸如.140.00008000.1等字符串。这是非常挑剔的-字符串必须匹配数字的"最小完美形式"才能通过此测试。

它使用StringNumber构造函数将字符串重新转换为数字,从而检查javascript引擎的"完美最小形式"(使用初始Number构造函数转换为的形式)是否与原始字符串匹配。


parseInt(),但请注意,在这个函数的意义上有点不同,例如它为parseInt返回100("100px")。


将参数传递给其构造函数时,可以使用数字的结果。

如果参数(字符串)无法转换为数字,则返回NaN,因此可以确定提供的字符串是否为有效数字。

注:当传递空字符串或'\t\t''
\t'
时,数字返回0;传递真将返回1,传递假将返回0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    Number('34.00') // 34
    Number('-34') // -34
    Number('123e5') // 12300000
    Number('123e-5') // 0.00123
    Number('999999999999') // 999999999999
    Number('9999999999999999') // 10000000000000000 (integer accuracy up to 15 digit)
    Number('0xFF') // 255
    Number('Infinity') // Infinity  

    Number('34px') // NaN
    Number('xyz') // NaN
    Number('true') // NaN
    Number('false') // NaN

    // cavets
    Number('    ') // 0
    Number('\t\t') // 0
    Number('
\t'
) // 0


我已经测试过了,迈克尔的解决方案是最好的。投票给他上面的答案(在这个页面上搜索"如果你真的想确定一个字符串"来找到它)。实质上,他的答案是:

1
2
3
4
function isNumeric(num){
  num ="" + num; //coerce num to be a string
  return !isNaN(num) && !isNaN(parseFloat(num));
}

它适用于我在这里记录的每个测试用例:网址:https://jsfiddle.net/wggehvp9/5/

对于这些边缘情况,许多其他解决方案都失败了:"",空,"",真,和[]。理论上,您可以使用它们,并进行适当的错误处理,例如:

1
return !isNaN(num);

1
return (+num === +num);

特别处理/ s/,null,",true,false,[](和其他?)


嗯,我用的是我做的这个……

到目前为止,它一直在工作:

1
2
3
4
5
6
function checkNumber(value) {
    if ( value % 1 == 0 )
    return true;
    else
    return false;
}

如果你发现它有什么问题,请告诉我。


报价:

isNaN(num) // returns true if the variable does NOT contain a valid number

如果您需要检查前导/尾随空格,则不是完全正确的-例如,当需要一定数量的数字时,您需要获得,例如"1111",而不是"111"或"111",可能是一个管脚输入。

更好使用:

1
var num = /^\d+$/.test(num)


为什么jquery的实现不够好?

1
2
3
4
function isNumeric(a) {
    var b = a && a.toString();
    return !$.isArray(a) && b - parseFloat(b) + 1 >= 0;
};

迈克尔提出了类似的建议(尽管我在这里偷了"user1691651-john"的修改版本):

1
2
3
4
function isNumeric(num){
    num ="" + num; //coerce num to be a string
    return !isNaN(num) && !isNaN(parseFloat(num));
}

下面是一个性能很可能很差但效果很好的解决方案。它是由jquery 1.12.4实现和michael的答案生成的一个装置,对前导/尾随空格进行额外检查(因为michael的版本对于前导/尾随空格的数字返回true):

1
2
3
4
5
6
7
function isNumeric(a) {
    var str = a +"";
    var b = a && a.toString();
    return !$.isArray(a) && b - parseFloat(b) + 1 >= 0 &&
           !/^\s+|\s+$/g.test(str) &&
           !isNaN(str) && !isNaN(parseFloat(str));
};

后一种版本有两个新的变量。通过这样做,人们可以绕过其中之一:

1
2
3
4
5
6
7
8
function isNumeric(a) {
    if ($.isArray(a)) return false;
    var b = a && a.toString();
    a = a +"";
    return b - parseFloat(b) + 1 >= 0 &&
            !/^\s+|\s+$/g.test(a) &&
            !isNaN(a) && !isNaN(parseFloat(a));
};

我还没有用任何其他方法来测试这些,除了手动测试我将用我目前的困境来打击的几个用例,这些都是非常标准的东西。这是一个"站在巨人肩膀上"的局面。


如果有人能做到这一点,我花了一些时间来破解这个补丁moment.js(https://github.com/moment/moment)。我从中拿走了一些东西:

1
2
3
4
5
6
function isNumeric(val) {
    var _val = +val;
    return (val !== val + 1) //infinity check
        && (_val === +val) //Cute coercion check
        && (typeof val !== 'object') //Array/object check
}

处理以下情况:

真的!:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
isNumeric("1"))
isNumeric(1e10))
isNumeric(1E10))
isNumeric(+"6e4"))
isNumeric("1.2222"))
isNumeric("-1.2222"))
isNumeric("-1.222200000000000000"))
isNumeric("1.222200000000000000"))
isNumeric(1))
isNumeric(0))
isNumeric(-0))
isNumeric(1010010293029))
isNumeric(1.100393830000))
isNumeric(Math.LN2))
isNumeric(Math.PI))
isNumeric(5e10))

错了!:

1
2
3
4
5
6
7
8
9
10
isNumeric(NaN))
isNumeric(Infinity))
isNumeric(-Infinity))
isNumeric())
isNumeric(undefined))
isNumeric('[1,2,3]'))
isNumeric({a:1,b:2}))
isNumeric(null))
isNumeric([1]))
isNumeric(new Date()))

具有讽刺意味的是,我正在与之斗争的是:

1
isNumeric(new Number(1)) => false

欢迎提出任何建议。:]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function isNumberCandidate(s) {
  const str = (''+ s).trim();
  if (str.length === 0) return false;
  return !isNaN(+str);
}

console.log(isNumberCandidate('1'));       // true
console.log(isNumberCandidate('a'));       // false
console.log(isNumberCandidate('000'));     // true
console.log(isNumberCandidate('1a'));      // false
console.log(isNumberCandidate('1e'));      // false
console.log(isNumberCandidate('1e-1'));    // true
console.log(isNumberCandidate('123.3'));   // true
console.log(isNumberCandidate(''));        // false
console.log(isNumberCandidate(' '));       // false
console.log(isNumberCandidate(1));         // true
console.log(isNumberCandidate(0));         // true
console.log(isNumberCandidate(NaN));       // false
console.log(isNumberCandidate(undefined)); // false
console.log(isNumberCandidate(null));      // false
console.log(isNumberCandidate(-1));        // true
console.log(isNumberCandidate('-1'));      // true
console.log(isNumberCandidate('-1.2'));    // true
console.log(isNumberCandidate(0.0000001)); // true
console.log(isNumberCandidate('0.0000001')); // true
console.log(isNumberCandidate(Infinity));    // true
console.log(isNumberCandidate(-Infinity));    // true

console.log(isNumberCandidate('Infinity'));  // true

if (isNumberCandidate(s)) {
  // use +s as a number
  +s ...
}


工作方案:

1
2
3
4
5
 function(check){
    check = check +"";
    var isNumber =   check.trim().length>0? !isNaN(check):false;
    return isNumber;
    }

我喜欢这个的简单。

1
Number.isNaN(Number(value))

上面是常规的javascript,但我将它与一个用于智能类型检查的typescript类型保护结合使用。这对于类型脚本编译器来说非常有用,可以为您提供正确的智能感知,并且没有类型错误。

打字字体保护

1
2
3
4
5
6
isNotNumber(value: string | number): value is string {
    return Number.isNaN(Number(this.smartImageWidth));
}
isNumber(value: string | number): value is number {
    return Number.isNaN(Number(this.smartImageWidth)) === false;
}

假设你有一个财产width,就是number | string。您可能需要根据它是否是字符串来进行逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var width: number|string;
width ="100vw";

if (isNotNumber(width))
{
    // the compiler knows that width here must be a string
    if (width.endsWith('vw'))
    {
        // we have a 'width' such as 100vw
    }
}
else
{
    // the compiler is smart and knows width here must be number
    var doubleWidth = width * 2;    
}

typeguard足够智能,可以将width的类型限制在if语句中,使其仅为string类型。这允许编译器允许width.endsWith(...),如果类型是string | number,则不允许这样做。

你想叫什么都行,你叫什么都行,isNotNumberisNumberisStringisNotString,但我觉得isString有点含糊不清,更难读。


为自己省去寻找"内置"解决方案的麻烦。

没有一个很好的答案,而且在这条线索中被大大否决的答案是错误的。

npm install is-number

In JavaScript, it's not always as straightforward as it should be to reliably check if a value is a number. It's common for devs to use +, -, or Number() to cast a string value to a number (for example, when values are returned from user input, regex matches, parsers, etc). But there are many non-intuitive edge cases that yield unexpected results:

1
2
3
4
console.log(+[]); //=> 0
console.log(+''); //=> 0
console.log(+'   '); //=> 0
console.log(typeof NaN); //=> 'number'


我的尝试有点混乱,不是最好的解决办法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function isInt(a){
    return a ===""+~~a
}


console.log(isInt('abcd'));         // false
console.log(isInt('123a'));         // false
console.log(isInt('1'));            // true
console.log(isInt('0'));            // true
console.log(isInt('-0'));           // false
console.log(isInt('01'));           // false
console.log(isInt('10'));           // true
console.log(isInt('-1234567890'));  // true
console.log(isInt(1234));           // true
console.log(isInt('123.4'));        // false
console.log(isInt(''));             // false

// other types then string returns false
console.log(isInt(5));              // false
console.log(isInt(undefined));      // false
console.log(isInt(null));           // false
console.log(isInt('0x1'));          // false
console.log(isInt(Infinity));       // false


使用纯javascript:

1
2
Number.isNaN(Number('1')); // false
Number.isNaN(Number('asdf')); // true

使用LADAS:

1
2
_.isNaN(_.toNumber('1')); // false
_.isNaN(_.toNumber('asdf')); // true

可以使用类型,如流库,以获得静态、编译时间检查。当然对用户输入不是很有用。

1
2
3
4
5
6
7
8
9
10
11
// @flow

function acceptsNumber(value: number) {
  // ...
}

acceptsNumber(42);       // Works!
acceptsNumber(3.14);     // Works!
acceptsNumber(NaN);      // Works!
acceptsNumber(Infinity); // Works!
acceptsNumber("foo");    // Error!

我的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// returns true for positive ints;
// no scientific notation, hexadecimals or floating point dots

var isPositiveInt = function(str) {
   var result = true, chr;
   for (var i = 0, n = str.length; i < n; i++) {
       chr = str.charAt(i);
       if ((chr <"0" || chr >"9") && chr !=",") { //not digit or thousands separator
         result = false;
         break;
       };
       if (i == 0 && (chr =="0" || chr ==",")) {  //should not start with 0 or ,
         result = false;
         break;
       };
   };
   return result;
 };

您可以在循环中添加其他条件,以满足您的特定需求。


在我的应用程序中,我们只允许a-z a-z和0-9个字符。我发现上面使用"string%1==0"的答案是有效的,除非字符串以0xnn(类似于0x10)开头,然后当我们不想返回它时,它会以数字形式返回。下面的数字检查中的简单陷阱在我们的特定情况下似乎起到了作用。

1
2
3
4
function isStringNumeric(str_input){  
    //concat a temporary 1 during the modulus to keep a beginning hex switch combination from messing us up  
    //very simple and as long as special characters (non a-z A-Z 0-9) are trapped it is fine  
    return '1'.concat(str_input) % 1 === 0;}

警告:这可能是在利用javascript和actionscript中的一个长期存在的bug[数字("1"+字符串)%1==0)],我不能这么说,但这正是我们需要的。


这里有一个一行程序来检查sNum是否是一个有效的数字值;它已经过各种输入的测试:

1
!isNaN(+s.replace(/\s|\$/g, ''));  // returns True if numeric value

我最近写了一篇关于如何确保变量是一个有效数字的文章:https://github.com/jehugaleahsa/artifacts/blob/master/2018/typescript_num_hack.md如果这很重要,文章解释了如何确保浮点或整数(+xvs ~~x)。

本文假设变量是一个string或一个number开头,trim可用/多填充。将它扩展到处理其他类型也不难。这是它的肉:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Check for a valid float
if (x == null
    || ("" + x).trim() ===""
    || isNaN(+x)) {
    return false;  // not a float
}

// Check for a valid integer
if (x == null
    || ("" + x).trim() ===""
    || ~~x !== +x) {
    return false;  // not an integer
}

只需使用isNaN(),这将把字符串转换成一个数字,如果得到一个有效的数字,将返回false

1
2
isNaN("Alireza"); //return true
isNaN("123"); //return false

我正在使用以下内容:

1
const isNumber = s => !isNaN(+s)

我是这样做的:

1
2
3
4
5
6
7
8
function isString(value)
{
    return value.length !== undefined;
}
function isNumber(value)
{
    return value.NaN !== undefined;
}

当然,如果传递其他定义了"length"的对象,isString()将在此处被触发。