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


当前回答

防止空字符串和null时

// Base cases that are handled properly
Number.isNaN(Number('1')); // => false
Number.isNaN(Number('-1')); // => false
Number.isNaN(Number('1.1')); // => false
Number.isNaN(Number('-1.1')); // => false
Number.isNaN(Number('asdf')); // => true
Number.isNaN(Number(undefined)); // => true

// Special notation cases that are handled properly
Number.isNaN(Number('1e1')); // => false
Number.isNaN(Number('1e-1')); // => false
Number.isNaN(Number('-1e1')); // => false
Number.isNaN(Number('-1e-1')); // => false
Number.isNaN(Number('0b1')); // => false
Number.isNaN(Number('0o1')); // => false
Number.isNaN(Number('0xa')); // => false

// Edge cases that will FAIL if not guarded against
Number.isNaN(Number('')); // => false
Number.isNaN(Number(' ')); // => false
Number.isNaN(Number(null)); // => false

// Edge cases that are debatable
Number.isNaN(Number('-0b1')); // => true
Number.isNaN(Number('-0o1')); // => true
Number.isNaN(Number('-0xa')); // => true
Number.isNaN(Number('Infinity')); // => false 
Number.isNaN(Number('INFINITY')); // => true  
Number.isNaN(Number('-Infinity')); // => false 
Number.isNaN(Number('-INFINITY')); // => true  

当不保护空字符串和null时

使用parseInt:

// Base cases that are handled properly
Number.isNaN(parseInt('1')); // => false
Number.isNaN(parseInt('-1')); // => false
Number.isNaN(parseInt('1.1')); // => false
Number.isNaN(parseInt('-1.1')); // => false
Number.isNaN(parseInt('asdf')); // => true
Number.isNaN(parseInt(undefined)); // => true
Number.isNaN(parseInt('')); // => true
Number.isNaN(parseInt(' ')); // => true
Number.isNaN(parseInt(null)); // => true

// Special notation cases that are handled properly
Number.isNaN(parseInt('1e1')); // => false
Number.isNaN(parseInt('1e-1')); // => false
Number.isNaN(parseInt('-1e1')); // => false
Number.isNaN(parseInt('-1e-1')); // => false
Number.isNaN(parseInt('0b1')); // => false
Number.isNaN(parseInt('0o1')); // => false
Number.isNaN(parseInt('0xa')); // => false

// Edge cases that are debatable
Number.isNaN(parseInt('-0b1')); // => false
Number.isNaN(parseInt('-0o1')); // => false
Number.isNaN(parseInt('-0xa')); // => false
Number.isNaN(parseInt('Infinity')); // => true 
Number.isNaN(parseInt('INFINITY')); // => true  
Number.isNaN(parseInt('-Infinity')); // => true 
Number.isNaN(parseInt('-INFINITY')); // => true 

使用parseFloat:

// Base cases that are handled properly
Number.isNaN(parseFloat('1')); // => false
Number.isNaN(parseFloat('-1')); // => false
Number.isNaN(parseFloat('1.1')); // => false
Number.isNaN(parseFloat('-1.1')); // => false
Number.isNaN(parseFloat('asdf')); // => true
Number.isNaN(parseFloat(undefined)); // => true
Number.isNaN(parseFloat('')); // => true
Number.isNaN(parseFloat(' ')); // => true
Number.isNaN(parseFloat(null)); // => true

// Special notation cases that are handled properly
Number.isNaN(parseFloat('1e1')); // => false
Number.isNaN(parseFloat('1e-1')); // => false
Number.isNaN(parseFloat('-1e1')); // => false
Number.isNaN(parseFloat('-1e-1')); // => false
Number.isNaN(parseFloat('0b1')); // => false
Number.isNaN(parseFloat('0o1')); // => false
Number.isNaN(parseFloat('0xa')); // => false

// Edge cases that are debatable
Number.isNaN(parseFloat('-0b1')); // => false
Number.isNaN(parseFloat('-0o1')); // => false
Number.isNaN(parseFloat('-0xa')); // => false
Number.isNaN(parseFloat('Infinity')); // => false 
Number.isNaN(parseFloat('INFINITY')); // => true  
Number.isNaN(parseFloat('-Infinity')); // => false 
Number.isNaN(parseFloat('-INFINITY')); // => true

笔记:

只有字符串、空值和未初始化值被认为与解决原始问题保持一致。如果考虑的值是数组和对象,则存在其他边情况。二进制、八进制、十六进制和指数表示法中的字符不区分大小写(即:“0xFF”、“0xFF”和“0xFF”等在上述测试用例中都会产生相同的结果)。在某些情况下,与Infinity(区分大小写)不同,Number和Math对象中的常量以字符串格式作为测试用例传递给上述任何方法,将被确定为不是数字。请参阅此处,了解如何将参数转换为数字,以及为什么存在空字符串和空字符串的边情况。

其他回答

如果您真的想确保字符串只包含一个数字、任何数字(整数或浮点)以及一个数字,则不能使用parseInt()/parseFloat()、number()或!isNaN()。注意!isNaN()实际上在Number()返回一个数字时返回true,在返回NaN时返回false,因此我将从后面的讨论中排除它。

parseFloat()的问题是,如果字符串包含任何数字,它将返回一个数字,即使字符串不只包含一个数字:

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

Number()的问题是,在传递的值根本不是数字的情况下,它将返回一个数字!

Number("") // returns 0
Number(" ") // returns 0
Number(" \u00A0   \t\n\r") // returns 0

滚动自己的正则表达式的问题是,除非您创建了与Javascript识别的浮点数匹配的精确正则表达式,否则您将错过案例或识别不应该出现的案例。即使您可以滚动自己的正则表达式,为什么?有更简单的内置方法来实现。

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

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))
}

你可以按照RegExp的方式:

var num = "987238";

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

老问题,但给出的答案中缺少几点。

科学记数法。

!isNaN('e+30')是正确的,但在大多数情况下,当人们要求数字时,他们不想匹配像1e+30这样的数字。

大浮点数的行为可能很奇怪

观察(使用Node.js):

> var s = Array(16 + 1).join('9')
undefined
> s.length
16
> s
'9999999999999999'
> !isNaN(s)
true
> Number(s)
10000000000000000
> String(Number(s)) === s
false
>

另一方面:

> 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
>

因此,如果期望String(Number(s))==s,那么最好将字符串限制在最多15位(省略前导零后)。

无穷

> typeof Infinity
'number'
> !isNaN('Infinity')
true
> isFinite('Infinity')
false
>

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

非科学记数法可预测地转换为数字并返回到字符串有限的

这不是一项容易的任务。下面是一个简单的版本:

  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);
  }

然而,即使是这一点也远未完成。这里不处理前导零,但它们确实会破坏长度测试。

我的解决方案:

// 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;
 };

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

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

本文假设变量是一个字符串或一个数字开头,trim可用/polyfulled。将其扩展到处理其他类型也不难。这是它的肉:

// 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
}