为什么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
函数时,采取以下步骤:
- 让
num
是?ToNumber(number)
。- 如果
num
是NaN
,则返回true
。- 否则,返回
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,未定义)之间都有标准转换。
String
到Number
的标准转换可以用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