为什么isNaN(“”)等于false

我有一个快速的问题(我希望!)。 在JS中,为什么isNaN(" ")评估为false,但是是否为“真isNaN(" x")

我正在对文本input字段执行数字操作,并检查字段是否为空,“”或NaN。 当有人在场上input一小部分空间时,我的validation都没有通过,所以我很困惑它为什么会通过isNAN检查。

谢谢!

JavaScript将空string解释为0,然后isNANtesting失败。 你可以先在string上使用parseInt,它不会将空string转换为0.结果应该失败isNAN。

你可能会发现这个令人惊讶的,或者可能不是,但这里有一些testing代码来显示你的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 

 "" != " " 

玩的开心 :)

尝试使用:

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

要么

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

要更好地理解它,请打开第43页上的“ Ecma-Script规范pdf ”“ToNumber应用于stringtypes”

如果一个string有一个数字语法,可以包含任意数量的空白字符,则可以将其转换为数字types。 空string的计算结果为0.另外string“Infinity”应该给

 isNaN('Infinity'); // false 

MDN原因你面临的问题

当isNaN函数的参数不是Numbertypes时,该值首先被强制为一个Number。 然后testing结果值以确定它是否是NaN。

您可能想要检查以下覆盖NaN比较平等的综合答案。

如何testingJavaScriptvariables是否为NaN

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

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

如果你想要实现一个准确的isNumber函数,这里有一个方法可以从Javascript中完成: Douglas Crockford 的Good Part [第105页]

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

不完全正确的答案

Antonio Haley的高度赞同和接受的答案在这里做了一个错误的假设,这个过程通过JavaScript的parseInt函数:

你可以在string上使用parseInt …结果应该失败isNAN。

我们可以很容易地用string"123abc"来驳斥这个陈述:

 parseInt("123abc") // 123 (a number... isNaN("123abc") // true ...which is not a number) 

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

正确答案

ECMAScript-262定义了在18.2.3节中 isNaN检查的工作原理。

18.2.3 isNaN (数字)

isNaN函数是%isNaN%内部对象。 当用一个参数号调用isNaN函数时,采取以下步骤:

  1. num是? ToNumber(number)
  2. 如果numNaN ,则返回true
  3. 否则,返回false

它引用的ToNumber函数也在ECMAScript-262的7.1.3节中定义。 在这里,我们被告知JavaScript如何处理传递给这个函数的string。

问题中给出的第一个例子是一个只包含空白字符的string。 本节规定:

一个空的或只包含空格的StringNumericLiteral被转换为+0

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

同一部分还指出:

如果语法不能将String解释为StringNumericLiteral的扩展,那么ToNumber的结果是NaN

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

我不知道为什么 ,但要解决这个问题,你总是可以在检查之前修剪空白。 无论如何,你可能都想这样做。

函数isNaN("")执行string到数字types的强制转换

ECMAScript 3-5为typeof运算符定义了以下返回值:

  • 未定义
  • 对象(null,对象,数组)
  • 布尔
  • function

最好把我们的testing包装在一个函数体中:

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

这个函数不是用来testingvariablestypes ,而是testing被强制的值 。 例如,布尔值和string被强制为数字,所以也许你可能想调用这个函数isNumberCoerced()

如果不需要testingstring数字以外的types ,那么下面的代码片段可能被用作某些条件的一部分:

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

我build议你使用下面的函数,如果你真的想要一个适当的检查,如果它是一个整数:

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

由于非数字被强制为数字types,那么这就是isNaN全局函数混淆行为的一部分。

来自MDN

由于isNaN函数规范的最早版本,其非数字参数的行为一直令人困惑。 当isNaN函数的参数不是Numbertypes时,该值首先被强制为一个Number。 然后testing结果值以确定它是否是NaN 。 因此,对于强制为数字types的非数字导致有效的非NaN数值(特别是空string和布尔基元,当强制数字值为零或一时),“假”返回值可能是意外的; 例如,空string肯定是“不是一个数字”。

还要注意,在ECMAScript 6中,现在还有Number.isNaN方法,根据MDN:

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

不幸的是

即使ECMAScript 6 Number.isNaN方法也有其自己的问题,如博客文章中所述 – 修复丑陋的JavaScript和ES6 NaN问题 。

isNaN将总是返回一个空string的错误。 我build议在评估之前进行string修整。

这个function似乎在我的testing中工作

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

关于什么

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

isNaN函数需要一个Number作为它的参数,所以任何其他types的参数(在你的情况下是一个string)将被转换为Number, 然后执行实际的函数逻辑。 (请注意, NaN也是Numbertypes的值!)

顺便说一句。 这对于所有内置函数是很常见的 – 如果他们期望某个types的参数,实际的参数将使用标准的转换函数进行转换。 所有基本types(布尔,string,数字,对象,date,null,未定义)之间都有标准转换。

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

  • Number(" ")计算结果为0
  • Number(" x")评估为NaN

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

真正的问题是为什么标准的string到数字转换就像它一样工作。 string到数字的转换实际上是为了将诸如“123”或“17.5e4”之类的数字string转换为相应的数字。 转换首先跳过最初的空格(所以“123”是有效的),然后尝试parsing其余的数字。 如果它不能作为数字parsing(“x”不是),那么结果是NaN。 但有一个明确的特殊规则,即将空白string或只有空白字符转换为0.所以这解释了转换。

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

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

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

它只是检查任何非数字(0-9),不是“ – ”或“。”,并且不是未定义,空或空的字符,如果没有匹配,则返回true。 🙂

JavaScript中内置的isNaN函数(默认情况下应该是这样)是一个“dynamictypes运算符”。 因此,所有的值(在DTC过程中)可能会产生一个简单的真实| 如"", " ", " 000" ,不能是NaN。

这意味着所提供的论据将首先经历如下转换

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

说明:

在函数体的第一行,我们(首先)试图成功地将参数转换成一个数字对象。 和(第二),使用点运算符,我们为了我们自己的方便,立即剥离创build的对象原始

在第二行中,我们把上一步得到的值和NaN不等于宇宙中的任何东西,甚至不等于它本身的优点,例如: NaN == NaN >> false来最终比较它(与不平等)本身。

这样,只有当提供的参数返回值是一个转换为数字对象的失败尝试,即一个非数字号码,函数返回才会返回true 。 如NaN。


isNaNstatic()

但是,对于静态types操作符(如果需要的话),如果需要的话,我们可以编写一个更简单的函数,例如:

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

并且完全避免DTC,以便如果参数不是显式的NaN编号,它将返回false。 因此,testing以下内容:

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

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

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

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

问候。

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

也就是说,isNaN(foo)等价于isNaN(Number(foo))它接受任何以数字为数字的string,这是显而易见的。 例如。

 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 

正如其他的解释, isNaN函数会在validation它之前将空string强制为数字,从而将空string变为0(这是一个有效数字)。 但是,我发现parseInt函数在试图parsing一个空string或一个只有空格的string时会返回NaN 。 因此,下面的组合似乎运作良好:

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

这个检查可以用于正数,负数和带小数点的数字,所以我相信它涵盖了所有常见的数字情况。

我用这个

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