为什么 Number('') 返回 0 而 parseInt('') 返回 NaN?

9

我浏览了StackOverflow上类似的问题和回答,并找到了这个:

parseInt("123hui")
returns 123

Number("123hui")
returns NaN

由于 parseInt() 只解析到第一个非数字字符并返回已解析的内容,而 Number() 则尝试将整个字符串转换为数字,所以在 parseInt('')Number('') 的情况下可能会出现不太符合预期的行为。

我认为理想情况下,parseInt 应该像对 Number("123hui") 一样返回 NaN

接下来是我的问题:

由于 0 == '' 返回 true,我认为它的解释方式类似于 0 == Number(''),这是正确的。那么编译器真的像 0 == Number('') 一样处理它,而不是像 0 == parseInt(''),还是我漏掉了什么要点?


7
好的,这只是它被设计成这样运作的方式,或者也许是进化到这种方式。无论哪种方式,现在已经太晚改变了。而且两种方法都有很好的应用案例。你只需要选择适合的那一种。 - Thilo
1
@JonathanLonowski已经给出了完美的解释。不过你可以参考这个标准http://www.ecma-international.org/ecma-262/5.1/#sec-15.7。 - gurvinder372
3
我不确定你期望得到哪种回答。你是想让别人为你引用规范,还是想知道这个设计决策的原因?如果是后者,那么在Stack Overflow上问这样的问题并不好。 - Felix Kling
2
@aProgrammer 这个问题是关于 JavaScript 的。-.- - T J
@TJ,哦,我的错误..我在想,怎么可能有人实例化一个抽象类... - Amit
显示剩余4条评论
3个回答

5
这种差异部分是由于Number()使用附加逻辑进行类型转换。它遵循的规则之一是:
  • 一个空的或仅包含空格的StringNumericLiteral被转换为+0
parseInt()的定义是仅查找和评估输入中的数字字符,基于给定或检测到的radix。并且,它被定义为期望至少一个有效字符。

13)如果S包含一个不是基数-R数字的代码单元,则让Z成为S中第一个这样的代码单元之前的所有代码单元的子字符串;否则,让Z成为S

14)如果Z为空,则返回NaN

注意:'S'是去除任何前导空格后的输入字符串。


作为0==''返回true,我认为它的解释类似于0==Number('') [...] ==使用的规则被定义为抽象相等。 而且,你对使用的强制/转换是正确的。相关步骤是#6: 如果x的类型是数字,y的类型是字符串, 返回比较x == ToNumber(y)的结果。

对于典型的相等比较(当您不尝试同时转换类型时),通常最好使用===而不是==,避免类型强制转换混淆。 - Thilo
@Thilo:嗯,当你不转换类型因为两者是相同的(正如它们应该是的),就没有混淆了,你也可以使用== - Bergi

0
回答你关于0==''返回true的问题:
下面是数字和字符串的比较: 等于运算符(==)
Type (x) Type(y)              Result
-------------------------------------------
x and y are the same type      Strict Equality (===) Algorithm
Number  String                 x == toNumber(y)

而 toNumber 函数将字符串参数转换为数字:

toNumber:

Argument type    Result
------------------------
String          In effect evaluates Number(string)
                 “abc” -> NaN
                 “123-> 123

Number('') 返回 0。这样你就得到了 0==0,它使用严格相等 (===) 算法进行评估。

严格相等运算符 (===)

Type            values                        Result
----------------------------------------------------------
Number       x same value as y                true
             (but not NaN)

您可以在javascriptweblog.wordpress.com - truth-equality-and-javascript找到完整的列表。


-1

parseInt("") 的结果是 NaN,因为标准规定如此,即使 +"" 的结果是 0(也只是因为标准规定如此,例如 "" == 0)。

不要试图在其中寻找逻辑,因为没有深刻的逻辑,只有历史

在我看来,你正在犯一个大错误……越早纠正,对你的 JavaScript 编程生涯就越有好处。这个错误是你假设编程语言中的每个选择和技术细节都是合乎逻辑的。这简直是不可能的。

特别是对于 JavaScript。

请记住,JavaScript 是匆忙“设计”的,仅仅因为命运的原因,它在一夜之间变得极其流行。这迫使社区在对细节进行任何严肃思考之前对其进行标准化,因此它基本上在任何严格的现场测试之前就被“冻结”在了当前可悲的状态。

有些部分太糟糕了,甚至不好笑(例如with语句或==相等运算符是如此糟糕,以至于严肃的JS IDE警告任何使用它:任何使用它:即使只使用普通值而没有任何“特殊”值,例如nullundefinedNaN或空字符串"",也会出现A==BB==CA!=C,而不是因为精度问题)。

在Javascript中,无意义的特殊情况无处不在,试图将它们放在逻辑框架中,很遗憾,是一种浪费的努力。通过阅读大量资料来学习其奇怪之处,并享受其提供的出色运行时环境(这就是Javascript真正闪耀的地方……浏览器及其JIT是真正令人印象深刻的技术:您可以编写几行代码,并在各种不同的计算设备上运行实际有用的软件)。

所有奇怪之处都被列举在官方标准中,但读起来非常困难,因为它旨在非常精确,而不幸的是,它必须指定的规则真的很复杂。

此外,随着语言功能的增加,规则会变得越来越复杂:例如,对于ES5而言,仅仅是另一个奇怪的“特殊”情况(例如Date对象的ToPrimitive操作行为),在ES6中成为了一个“正常”的情况(其中ToPrimitive可以被自定义)。
不确定这种“正常化”是否值得高兴...真正的问题是起点被冻结了,现在没有简单的解决方案(如果你不想扔掉所有现有的JavaScript代码的话)。
一门语言的正常路径是从干净、漂亮、对称和小型开始。然后当面临现实世界的问题时,语言就会获得(被感染)一些丑陋的部分(因为世界是丑陋和不对称的)。
JavaScript就是这样。只不过它没有从一个漂亮、干净的起点开始,而且在投入使用之前没有时间去完善它。

1
使用==的示例很糟糕:在许多语言中(甚至是编译语言中),==不具有传递性。 - zerkms
3
这是一个非常主观的回复,只是一篇长评论。我认为你错过了JavaScript作为一种简单易用的脚本语言的整个重点,其中像 == 运算符这样的特性是有意义的(例如,'1' == 1) 。 - RobG
1
@RobG: ==规则并不使JavaScript易于使用,实际上恰恰相反。你最终会得到一些有时工作有时不工作的程序,原因似乎毫无道理。顺便说一下,1也等于[1]"1 "(末尾有空格)。但是[1]不等于"1 "。这些规则并不简单,而是相当复杂和奇怪(查看ECMAScript正式标准可以找到一些有趣的东西)...它们只是对最初的黑客行为进行形式化。虽然成为一个黑客令人印象深刻,但仍然只是一个没有经过充分推敲的黑客行为。 - 6502
虽然我可能同意你的一些观点,但这只是发牢骚,不是答案。 - Bergi
@Bergi:实际上我非常喜欢 JavaScript ,很抱歉这一点并不明显。我试着重新措辞回答,将关于 +"" 的细节放在前面,希望让它听起来不那么“发牢骚”。我仍然认为试图将 JavaScript 定义在逻辑上下文中是一个严重的错误…… - 6502

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接