为什么isNaN(“”)等于false

时间:2009-05-05 15:21:15

标签: javascript nan mean

我有一个简单的问题(我希望!)。在JS中,为什么isNaN(" ")求值为false,但isNaN(" x")求值为true?

我正在对文本输入字段执行数值运算,并检查该字段是否为空,“”或NaN。当有人在场中键入少量空格时,我的验证在所有三个空格中都失败了,我很困惑为什么它超过了isNAN检查。

谢谢!

24 个答案:

答案 0 :(得分:145)

JavaScript将空字符串解释为0,然后无法通过isNAN测试。你可以先在字符串上使用parseInt,它不会将空字符串转换为0.结果应该是失败的isNAN。

答案 1 :(得分:76)

您可能会发现这个令人惊讶或者可能没有,但这里有一些测试代码可以向您展示JavaScript引擎的古怪。

document.write(isNaN("")) // false
document.write(isNaN(" "))  // false
document.write(isNaN(0))  // false
document.write(isNaN(null)) // false
document.write(isNaN(false))  // false
document.write("" == false)  // true
document.write("" == 0)  // true
document.write(" " == 0)  // true
document.write(" " == false)  // true
document.write(0 == false) // true
document.write(" " == "") // false

所以这意味着

" " == 0 == false

"" == 0 == false

但是

"" != " "

玩得开心:)

答案 2 :(得分:16)

为了更好地理解它,请打开第43页的Ecma-Script spec pdf“ToNumber应用于字符串类型”

如果字符串具有数字语法,可以包含任意数量的空格字符,则可以将其转换为数字类型。空字符串的计算结果为0.此外,字符串'Infinity'应该给出

isNaN('Infinity'); // false

答案 3 :(得分:15)

尝试使用:

alert(isNaN(parseInt("   ")));

或者

alert(isNaN(parseFloat("    ")));

答案 4 :(得分:6)

MDN原因来看你遇到的问题

  

当isNaN函数的参数不是Number类型时,该值首先被强制转换为Number。然后测试结果值以确定它是否是NaN。

您可能需要查看以下全面的答案,其中包含NaN对比的平等性。

  

How to test if a JavaScript variable is NaN

答案 5 :(得分:5)

我认为这是因为Javascript的输入:' '被转换为零,而'x'则不是:

alert(' ' * 1); // 0
alert('x' * 1); // NaN

答案 6 :(得分:4)

如果你想实现一个准确的isNumber函数,这里有一种方法可以通过Douglas Crockford的 Javascript:The Good Parts 进行[第105页]

var isNumber = function isNumber(value) {
   return typeof value === 'number' && 
   isFinite(value);
}

答案 7 :(得分:4)

不完全正确的答案

Antonio Haley highly upvoted and accepted answer在此假设此过程通过JavaScript的parseInt函数:

  

你可以在字符串上使用parseInt ......结果应该是失败的是NAN。

我们可以使用字符串"123abc"

轻松反驳此声明
parseInt("123abc")    // 123     (a number...
isNaN("123abc")       // true     ...which is not a number)

有了这个,我们可以看到JavaScript的parseInt函数返回"123abc"作为数字123,但其isNaN函数告诉我们{{1} 不是一个数字。

正确答案

ECMAScript-262定义"123abc"检查在section 18.2.3中的工作方式。

  

18.2.3 isNaN(数字)

     

isNaN函数是isNaN内在对象。当使用一个参数号调用%isNaN%函数时,将执行以下步骤:

     
      
  1. isNaN成为? num
  2.   
  3. 如果ToNumber(number)num,请返回NaN
  4.   
  5. 否则,请返回true
  6.   

它引用的false函数也在ECMAScript-262's section 7.1.3中定义。在这里,我们了解JavaScript如何处理传入此函数的字符串。

问题中给出的第一个示例是一个只包含空格字符的字符串。本节说明:

  

ToNumber为空或仅包含空格会转换为StringNumericLiteral

+0示例字符串因此转换为" ",这是一个数字。

同一部分还指出:

  

如果语法无法将+0解释为String的扩展,则StringNumericLiteral的结果为ToNumber

在不引用该部分中包含的所有检查的情况下,问题中给出的NaN示例属于上述条件,因为它不能被解释为" x"。因此,StringNumericLiteral会转换为" x"

答案 8 :(得分:2)

我不确定为什么,但为了解决这个问题,您可以在检查前始终修剪空白。无论如何,你可能想要这样做。

答案 9 :(得分:2)

函数isNaN("")执行字符串到数字类型强制

ECMAScript 3-5 defines the following return values for the typeof operator:

  • 未定义
  • object(null,objects,arrays)
  • 布尔
  • 字符串
  • 功能

最好将我们的测试包装在函数体中:

function isNumber (s) {
    return typeof s == 'number'? true
           : typeof s == 'string'? (s.trim() === ''? false : !isNaN(s))
           : (typeof s).match(/object|function/)? false
           : !isNaN(s)
}

此函数无意测试变量 type ,而是测试强制值。例如,布尔值和字符串被强制转换为数字,因此您可能希望将此函数称为isNumberCoerced()

如果不需要测试 string number 以外的类型,那么下面的代码段可能会被用作某些条件的一部分:

if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
    alert("s is a number")

答案 10 :(得分:1)

如果您真的想要检查它是否为整数,我建议您使用以下函数:

function isInteger(s)
{
   return Math.ceil(s) == Math.floor(s);
}

答案 11 :(得分:1)

isNaN(" ")为false是isNaN全局函数混淆行为的一部分,因为它将非数字强制转换为数字类型。

来自MDN

  

isNaN函数规范的最早版本以来,它对非数字参数的行为一直令人困惑。当isNaN函数的参数不是Number类型时,该值首先被强制转换为Number。然后测试结果值以确定它是否是NaN。因此,对于非数字,当强制转换为数字类型时会产生有效的非NaN数值(特别是空字符串和布尔基元,当强制赋予数值0或1时),“false”返回值可能是意外的;例如,空字符串肯定是“不是数字。”

另请注意,对于ECMAScript 6,现在还有Number.isNaN方法,根据MDN:

  

与全局isNaN()函数相比,Number.isNaN()不会遇到强制将参数转换为数字的问题。这意味着现在可以安全地传递通常会转换为NaN的值,但实际上与NaN的值不同。这也意味着只有类型编号的值NaN才会返回true

<强>不幸的是

即使是ECMAScript 6 Number.isNaN方法也存在问题,如博客文章Fixing the ugly JavaScript and ES6 NaN problem中所述。

答案 12 :(得分:1)

正如其他人所解释的那样,isNaN函数会在验证之前将空字符串强制转换为数字,从而将空字符串更改为0(这是一个有效数字)。 但是,我发现在尝试解析空字符串或仅包含空格的字符串时,parseInt函数将返回NaN。因此,以下组合似乎运作良好:

if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');

此检查适用于正数,负数和带小数点的数字,因此我认为它涵盖了所有常见的数字情况。

答案 13 :(得分:0)

let isNotNumber = val => isNaN(val) || (val.trim && val.trim() === '');

console.log(isNotNumber(' '));
console.log(isNotNumber('1'));
console.log(isNotNumber('123x'));
console.log(isNotNumber('x123'));
console.log(isNotNumber('0'));
console.log(isNotNumber(3));
console.log(isNotNumber('    x'));
console.log(isNotNumber('1.23'));
console.log(isNotNumber('1.23.1.3'));

if(!isNotNumber(3)){
  console.log('This is a number');
}

答案 14 :(得分:0)

我发现使用特定于Number类的方法很方便(因为其他进行转换的函数(例如parseInt)对于其中的某些值具有不同的输出)并使用原型继承。

Object.assign(Number.prototype, {
  isNumericallyValid(num) {
    if (
      num === null
      || typeof num === 'boolean'
      || num === ''
      || Number.isNaN(Number(num))
    ) {
      return false;
    }
    return true;
  }
});

答案 15 :(得分:0)

在检查带有空格或" "的某些字符串值是否为isNaN时,可以尝试执行字符串验证,例如:

// value = "123 " if (value.match(/\s/) || isNaN(value)) { // do something }

答案 16 :(得分:0)

NaN!==“不是数字”

NaN是数字类型的值

这是ECMAScript中isNaN()的定义

1. Let num be ToNumber(number).
2. ReturnIfAbrupt(num).
3. If num is NaN, return true.
4. Otherwise, return false.

尝试将任何值转换为数字。

Number(" ") // 0
Number("x") // NaN
Number(null) // 0

如果要确定值是否为NaN,则应首先尝试将其转换为数字值。

答案 17 :(得分:0)

我用这个

    function isNotANumeric(val) {
    	if(val.trim && val.trim() == "") {
         return true;
      } else {
      	 return isNaN(parseFloat(val * 1));
      }
    }
    
    alert(isNotANumeric("100"));  // false
    alert(isNotANumeric("1a"));   // true
    alert(isNotANumeric(""));     // true
    alert(isNotANumeric("   "));  // true

答案 18 :(得分:0)

isNAN(<argument>)是一个判断给定参数是否为非法数字的函数。 isNaN将参数转换为Number类型。如果要检查参数是否为数字?请在jQuery中使用$.isNumeric()函数。

也就是说,isNaN(foo)相当于isNaN(Number(foo)) 出于显而易见的原因,它接受任何带有所有数字作为数字对于前。

isNaN(123) //false
isNaN(-1.23) //false
isNaN(5-2) //false
isNaN(0) //false
isNaN('123') //false
isNaN('Hello') //true
isNaN('2005/12/12') //true
isNaN('') //false
isNaN(true) //false
isNaN(undefined) //true
isNaN('NaN') //true
isNaN(NaN) //true
isNaN(0 / 0) //true

答案 19 :(得分:0)

JavaScript 内置 isNaN 功能,默认情况下应为“动态类型操作符”。 因此,(在DTC过程中)所有的值都可能产生一个简单的真值如"", " ", " 000"之类的错误,不能是NaN。

意味着提供的参数将首先进行转换,如下所示:

function isNaNDemo(arg){
   var x = new Number(arg).valueOf();
   return x != x;
}

<强>解释

在函数体的顶行,我们(首先)尝试将参数成功转换为数字对象。并且(第二),使用点运算符 - 为了我们自己的方便 - 立即剥离,创建对象的原始

在第二行中,我们将获取上一步中获得的值,以及 NaN 与Universe中的任何内容不相等的优势,甚至不是自己,例如:NaN == NaN >> false最终将它(不平等)与自身进行比较。

这样,只有在提供的参数返回失败尝试转换为数字对象时,函数返回才会产生 true ,即,一个非数字号码;例如,NaN。

isNaNstatic()

但是,对于静态类型运算符 - 如果需要并且在需要时 - 我们可以编写一个更简单的函数,例如:

function isNaNstatic(x){   
   return x != x;
}

完全避免使用DTC,这样如果参数不是明确的NaN号,它将返回false。因此,测试以下内容:

isNaNStatic(" x"); // will return false因为它仍然是一个字符串。

然而: 例如isNaNStatic(1/"x"); // will of course return true. isNaNStatic(NaN); >> true

但与isNaN相反,isNaNStatic("NaN"); >> false因为它(参数)是一个普通的字符串。

P.S .: isNaN的静态版本在现代编码场景中非常有用。这可能是我花时间发布这个的主要原因之一。

问候。

答案 20 :(得分:0)

我写了这个快速的小函数来帮助解决这个问题。

function isNumber(val) {
     return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};

它只是检查任何不是数字(0-9)的字符,它们不是&#39; - &#39;或者&#39;。&#39;,并且没有未定义,null或为空,如果没有匹配则返回true。 :)

答案 21 :(得分:0)

isNaN函数需要一个Number作为其参数,因此任何其他类型的参数(在您的情况下为字符串)将在执行实际函数逻辑之前转换为Number 。 (请注意,NaN也是Number类型的值!)

顺便说一下。这对于所有内置函数来说很常见 - 如果它们期望某个类型的参数,则实际参数将使用标准转换函数进行转换。所有基本类型之间都有标准转换(bool,string,number,object,date,null,undefined。)

可以使用String显式调用NumberNumber()的标准转换。所以我们可以看到:

  • Number(" ")评估为0
  • Number(" x")评估为NaN

鉴于此,isNaN函数的结果完全合乎逻辑!

真正的问题是为什么标准的String-to-Number转换就像它一样工作。字符串到数字的转换实际上是将数字字符串(如“123”或“17.5e4”)转换为等效数字。转换首先跳过初始空格(因此“123”有效),然后尝试将休止符解析为数字。如果它不是可解析的数字(“x”不是),则结果为NaN。但是有一个明确的特殊规则,即一个空的或只有空格的字符串被转换为0.所以这解释了转换。

参考:http://www.ecma-international.org/ecma-262/5.1/#sec-9.3.1

答案 22 :(得分:0)

怎么样?
function isNumberRegex(value) {        
    var pattern = /^[-+]?\d*\.?\d*$/i;
    var match = value.match(pattern);
    return value.length > 0 && match != null;
}

答案 23 :(得分:0)

这个功能似乎在我的测试中起作用

function isNumber(s) {
    if (s === "" || s === null) {
        return false;
    } else {
        var number = parseInt(s);
        if (number == 'NaN') {
            return false;
        } else {
            return true;
        }
    }
}