为什么 isNaN(" ") (带空格的字符串)等于 false?
在 JavaScript 中,为什么 isNaN(" ")
计算结果为 false
,而 isNaN(" x")
计算结果为 true?
我正在对文本输入字段执行数字运算,并检查该字段是否为 null
、""
或 NaN
。 当有人在字段中输入少量空格时,我的验证在所有三个空格上都会失败,并且我很困惑为什么它会通过 isNaN
检查。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(25)
JavaScript 将空字符串解释为 0,从而导致 isNAN 测试失败。 您可以先对字符串使用 parseInt,这不会将空字符串转换为 0。结果应该会失败 isNAN。
JavaScript interprets an empty string as a 0, which then fails the isNAN test. You can use parseInt on the string first which won't convert the empty string to 0. The result should then fail isNAN.
您可能会感到惊讶,也可能不会,但这里有一些测试代码,可以向您展示 JavaScript 引擎的古怪之处。
所以这意味着
玩得
,但是
开心:)
You may find this surprising or maybe not, but here is some test code to show you the wackyness of the JavaScript engine.
so this means that
and
but
Have fun :)
为了更好地理解它,请打开 Ecma-Script 规范 pdf第 43 页“ToNumber 应用于字符串类型”
如果字符串具有数字语法,可以包含任意数量的空白字符,则可以将其转换为 Number 类型。 空字符串的计算结果为 0。字符串 'Infinity' 也应该给出
To understand it better, please open Ecma-Script spec pdf on page 43 "ToNumber Applied to the String Type"
if a string has a numerical syntax, which can contain any number of white-space characters, it can be converted to Number type. Empty string evaluates to 0. Also the string 'Infinity' should give
尝试使用:
或者
Try using:
Or
来自
MDN
原因对于您面临的问题您可能需要检查以下综合答案,其中还涵盖了 NaN 相等性比较。
From
MDN
reason for the issue you are facingYou may want to check the following comprehensive answer which covers the NaN comparison for equality as well.
我认为这是因为 Javascript 的输入:
' '
被转换为零,而'x'
则不是:I think it's because of Javascript's typing:
' '
is converted to zero, whereas'x'
isn't:不完全正确的答案
Antonio Haley 的高度赞成并接受的答案在这里做出了一个错误的假设,即这个过程通过 JavaScript 的 <代码>parseInt函数:
我们可以很容易地用字符串
"123abc"
反驳这个说法:通过这个,我们可以看到 JavaScript 的
parseInt
函数返回"123abc"
作为数字123
,但其isNaN
函数告诉我们"123abc"
不是 一个数字。正确答案
ECMAScript-262 定义了
isNaN
检查在 第 18.2.3 节。它引用的
ToNumber
函数也在 ECMAScript-262 的第 7.1 节中定义.3。 在这里,我们了解 JavaScript 如何处理传入此函数的字符串。问题中给出的第一个示例是一个仅包含空格字符的字符串。 本节规定:
因此,
" "
示例字符串被转换为+0
,这是一个数字。同一节还指出:
如果不引用该部分中包含的所有检查,问题中给出的
" x"
示例就会属于上述情况,因为它不能解释为StringNumericLiteral
。 因此," x"
被转换为NaN
。The Not-Entirely-Correct Answer
Antonio Haley's highly upvoted and accepted answer here makes a wrong assumption that this process goes through JavaScript's
parseInt
function:We can easily disprove this statement with the string
"123abc"
:With this, we can see that JavaScript's
parseInt
function returns"123abc"
as the number123
, yet itsisNaN
function tells us that"123abc"
isn't a number.The Correct Answer
ECMAScript-262 defines how the
isNaN
check works in section 18.2.3.The
ToNumber
function it references is also defined in ECMAScript-262's section 7.1.3. In here, we get told how JavaScript handles Strings which are passed in to this function.The first example given in the question is a string containing nothing but white space characters. This section states that:
The
" "
example string is therefore converted to+0
, which is a number.The same section also states:
Without quoting all of the checks contained within that section, the
" x"
example given in the question falls into the above condition as it cannot be interpreted as aStringNumericLiteral
." x"
is therefore converted toNaN
.函数
isNaN("")
执行字符串到数字类型的强制转换ECMAScript 3-5 为 typeof 运算符定义了以下返回值:
最好将我们的测试包装在函数体中:
此函数并非旨在测试变量类型,而是测试强制值。 您可能希望将此函数调用为
isNumberCoerced()
例如,布尔值和字符串被强制转换为数字,因此如果不需要测试除 类型 以外的类型, >字符串和数字,那么以下代码片段可以用作某些条件的一部分:
The function
isNaN("")
performs a String to Number type coercionECMAScript 3-5 defines the following return values for the typeof operator:
Better to wrap our test in a function body:
This function is not intented to test variable type, instead it tests the coerced value. For instance, booleans and strings are coerced to numbers, so perhaps you may want to call this function as
isNumberCoerced()
if there's no need to test for types other than string and number, then the following snippet might be used as part of some condition:
如果您想实现精确的 isNumber 函数,可以使用 Douglas Crockford 的 Javascript:The Good Parts [第 105 页] 中的一种方法。
If you would like to implement an accurate isNumber function, here is one way to do it from Javascript: The Good Parts by Douglas Crockford [page 105]
NaN
!== "not a number"NaN
是 Number 类型的值,这是 ECMAScript 中 isNaN() 的定义
尝试将任何值转换为 Number。
如果你想判断该值是否为
NaN
,你应该先尝试将其转换为Number值。NaN
!== "not a number"NaN
is a value of Number Typethis is a definition of isNaN() in ECMAScript
Try to convert any value to Number.
If you want to determine if the value is
NaN
, you should try to convert it to a Number value firstly.如果您确实想要正确检查它是否是整数,我建议您使用以下函数:
I suggest you to use the following function if you really want a proper check if it is an integer:
isNaN(" ")
为 false 是isNaN
全局函数令人困惑的行为的一部分,因为它将非数字强制转换为数字类型。来自 MDN :
另请注意,在 ECMAScript 6 中,现在还提供了
Number.isNaN
方法,根据 MDN:不幸的是:
即使是 ECMAScript 6
Number.isNaN
方法也有其自身的问题,如博客文章中所述 - 修复丑陋的 JavaScript 和 ES6 NaN 问题。That
isNaN(" ")
is false is part of the confusing behavior of theisNaN
global function due to its coercion of non-numbers to a numeric type.From MDN:
Note also that with ECMAScript 6, there is also now the
Number.isNaN
method, which according to MDN:Unfortunately:
Even the ECMAScript 6
Number.isNaN
method has its own issues, as outlined in the blog post - Fixing the ugly JavaScript and ES6 NaN problem.isNaN
函数需要一个 Number 作为其参数,因此任何其他类型的参数(在您的情况下为字符串)将在执行实际函数逻辑之前转换为 Number。 (请注意NaN
也是 Number 类型的值!)顺便说一句。 这对于所有内置函数来说很常见 - 如果它们需要某种类型的参数,则实际参数将使用标准转换函数进行转换。 所有基本类型(bool、string、number、object、date、null、undefined)之间都有标准转换。
String
到Number
的标准转换可以显式调用与Number()
。 所以我们可以看到:Number(" ")
计算结果为0
Number(" x")
计算结果为NaN
>鉴于此,
isNaN
函数的结果是完全符合逻辑的!真正的问题是为什么标准字符串到数字的转换会像这样工作。 字符串到数字的转换实际上旨在将“123”或“17.5e4”等数字字符串转换为等效的数字。 转换首先跳过初始空格(因此“123”有效),然后尝试将其余部分解析为数字。 如果它不可解析为数字(“x”则不可解析),则结果为 NaN。 但是有一个明确的特殊规则,即空字符串或只有空格的字符串将转换为 0。因此这解释了转换。
参考:http://www.ecma-international.org/ ecma-262/5.1/#sec-9.3.1
The
isNaN
function expects a Number as its argument, so arguments of any other type (in your case a string) will be converted to Number before the actual function logic is performed. (Be aware thatNaN
is also a value of type Number!)Btw. this is common for all built-in functions - if they expect an argument of a certain type, the actual argument will be converted using the standard conversion functions. There are standard conversions between all the basic types (bool, string, number, object, date, null, undefined.)
The standard conversion for
String
toNumber
can be invoked explicit withNumber()
. So we can see that:Number(" ")
evaluates to0
Number(" x")
evaluates toNaN
Given this, the result of the
isNaN
function is completely logical!The real question is why the standard String-to-Number conversion works like it does. The string-to-number conversion is really intended to convert numeric strings like "123" or "17.5e4" to the equivalent numbers. The conversion first skips initial whitespace (so " 123" is valid) and then tries to parse the rests as a number. If it is not parseable as a number ("x" isn't) then the result is NaN. But there is the explicit special rule that a string which is empty or only whitespace is converted to 0. So this explains the conversion.
Reference: http://www.ecma-international.org/ecma-262/5.1/#sec-9.3.1
我不确定为什么,但为了解决这个问题,您可以在检查之前删除空格。 无论如何你可能都想这样做。
I'm not sure why, but to get around the problem you could always trim whitespace before checking. You probably want to do that anyway.
我编写了这个快速的小函数来帮助解决这个问题。
它只是检查非数字 (0-9)、非“-”或“.”以及非未定义、null 或空的任何字符,如果没有匹配则返回 true。 :)
I wrote this quick little function to help solve this problem.
It simply checks for any characters that aren't numeric (0-9), that aren't '-' or '.', and that aren't undefined, null or empty and returns true if there's no matches. :)
正如其他人所解释的,isNaN 函数会在验证空字符串之前将其强制转换为数字,从而将空字符串更改为 0(这是一个有效的数字)。
但是,我发现当尝试解析空字符串或仅包含空格的字符串时,parseInt 函数将返回 NaN。 因此,以下组合似乎运行良好:
if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');
此检查将起作用对于正数、负数和带小数点的数字,所以我相信它涵盖了所有常见的数字情况。
As other explained the
isNaN
function will coerce the empty string into a number before validating it, thus changing an empty string into 0 (which is a valid number).However, I found that the
parseInt
function will returnNaN
when trying to parse an empty string or a string with only spaces. As such the following combination seems to be working well:if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');
This check will work for positive numbers, negative numbers and numbers with a decimal point, so I believe it covers all common numerical cases.
我用这个
I use this
这个功能在我的测试中似乎有效
This function seemed to work in my tests
关于什么
What about
JavaScript 内置 isNaN 函数 - 正如默认情况下所预期的 - 一个“动态类型运算符”。
因此,(在 DTC 过程中)可能产生简单 true | 的所有值。 false 例如
""、" "、" 000"
,不能为 NaN。这意味着提供的参数将首先进行转换,如下所示:
解释:
在函数体的顶行中,我们(首先)尝试成功地将参数转换为数字对象。 (第二),为了方便起见,我们使用点运算符立即剥离所创建对象的原始值。
在第二行中,我们采用上一步中获得的值,并且利用 NaN 不等于宇宙中任何东西的事实,甚至不等于本身,例如:
NaN == NaN >>> false
最终将其与自身进行比较(是否不平等)。这样,仅当且仅当提供的参数返回尝试转换为数字对象失败时,函数返回才会产生 true,即,不是-a-number; 例如,NaN。
isNaNstatic( )
但是,对于静态类型运算符 - 如果需要并且在需要时 - 我们可以编写一个简单得多的函数,例如:
并完全避免 DTC,这样如果参数不是明确的 NaN 数,它将返回 false。 因此,针对以下内容进行测试:
isNaNStatic(" x"); // 将返回 false
因为它仍然是一个字符串。然而:
isNaNStatic(1/"x"); // 当然会返回 true。 例如
isNaNStatic(NaN); >>> 正确。
但与
isNaN
相反,isNaNStatic("NaN"); >>> false
因为它(参数)是一个普通字符串。附:
isNaN 的静态版本在现代编码场景中非常有用。 这很可能是我花时间发布此内容的主要原因之一。
问候。
The JavaScript built-in isNaN function, is - as should be expected by default - a "Dynamic Type Operator".
Therefore all values which (during the DTC process) may yield a simple true | false such as
"", " ", " 000"
, cannot be NaN.Meaning that the argument supplied will first undergo a conversion as in:
Explanation:
In the top line of the function body, we are (first) trying to successfully convert the argument into a number object. And (second), using the dot operator we are - for our own convenience - immediately stripping off, the primitive value of the created object.
In the second line, we are taking the value obtained in the previous step, and the advantage of the fact that NaN is not equal to anything in the universe, not even to itself, e.g.:
NaN == NaN >> false
to finally compare it (for inequality) with itself.This way the function return will yield true only when, and only if, the supplied argument-return, is a failed attempt of conversion to a number object, i.e., a not-a-number number; e.g., NaN.
isNaNstatic( )
However, for a Static Type Operator - if needed and when needed - we can write a far simpler function such as:
And avoid the DTC altogether so that if the argument is not explicitly a NaN number, it will return false. Wherefore, testing against the following:
isNaNStatic(" x"); // will return false
because it's still a string.However:
isNaNStatic(1/"x"); // will of course return true.
as will for instanceisNaNStatic(NaN); >> true
.But contrary to
isNaN
, theisNaNStatic("NaN"); >> false
because it (the argument) is an ordinary string.p.s.:
The static version of isNaN can be very useful in modern coding scenarios. And it may very well be one of the main reasons I took my time for posting this.
Regards.
isNAN()
是一个判断给定参数是否为非法数字的函数。isNaN
将参数类型转换为 Number 类型。 如果你想检查参数是否是数字? 请使用 jQuery 中的$.isNumeric()
函数。即 isNaN(foo) 等价于 isNaN(Number(foo))
出于显而易见的原因,它接受所有数字都为数字的任何字符串。 对于前。
isNAN(<argument>)
is a function to tell whether given argument is illegal number.isNaN
typecasts the arguments into Number type. If you want to check if argument is Numeric or not? Please use$.isNumeric()
function in jQuery.That is, isNaN(foo) is equivalent to isNaN(Number(foo))
It accepts any strings having all numerals as numbers for obvious reasons. For ex.
当检查带有空格或
" "
的某个字符串值是否为isNaN
时,可能会尝试执行字符串验证,例如:// value = "123 "
if (value.match(/\s/) || isNaN(value)) {
// 做一点事
}
When checking if certain string value with whitespace or
" "
isisNaN
maybe try to perform string validation, example :// value = "123 "
if (value.match(/\s/) || isNaN(value)) {
// do something
}
我发现拥有一个特定于 Number 类的方法(因为其他执行转换(如 parseInt)的函数对于其中一些值有不同的输出)并使用原型继承是很方便的。
I find it convenient to have a method specific to the Number class (since other functions that do conversions like parseInt have different outputs for some of these values) and use prototypal inheritance.
我使用以下内容。
x=(isNaN(parseFloat(x)))? 0.00:parseFloat(x);
I use the following.
x=(isNaN(parseFloat(x)))? 0.00 : parseFloat(x);