parseInt(null,24)=== 23 ......等等,什么?

时间:2011-06-23 19:48:18

标签: javascript parseint

好吧,所以我正在搞乱parseInt以了解它如何处理尚未初始化的值,我偶然发现了这个宝石。对于任何24或以上的基数,都会发生以下情况。

parseInt(null, 24) === 23 // evaluates to true

我在IE,Chrome和Firefox中对它进行了测试,并且它们都是正确的,所以我认为它必须在某个地方的规范中。快速谷歌搜索没有给我任何结果所以我在这里,希望有人可以解释。

我记得听过Crockford的演讲,他说typeof null === "object"是因为疏忽导致Object和Null在内存中有一个几乎相同的类型标识符,或者沿着这些行,但我找不到那个视频现在

试一试:http://jsfiddle.net/robert/txjwP/

编辑更正:较高的基数返回不同的结果,32返回785077
编辑2 来自zzzzBov:[24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745


TL;博士

解释为什么parseInt(null, 24) === 23是真实的陈述。

6 个答案:

答案 0 :(得分:234)

它正在将null转换为字符串"null"并尝试转换它。对于基数0到23,它没有可以转换的数字,因此返回NaN。在24处,将{14}字母"n"添加到数字系统中。在31处,添加第21个字母"u",并且可以解码整个字符串。在37处,不再有任何有效数字集可以生成并返回NaN。

js> parseInt(null, 36)
1112745

>>> reduce(lambda x, y: x * 36 + y, [(string.digits + string.lowercase).index(x) for x in 'null'])
1112745

答案 1 :(得分:117)

Mozilla tells us

  

函数parseInt 转换它的第一个   字符串的参数,解析它,和   返回一个整数或NaN。如果不是NaN,   返回的值将是小数   第一个的整数表示   作为数字的参数   指定的基数(基数)。例如,a   基数为10表示转换自   十进制数,8八进制,16   十六进制,等等。对于radices   10以上,字母表的字母   表示大于9的数字   例如,十六进制数字(基数   16),使用A到F.

the spec中,15.1.2.2/1告诉我们使用内置ToString执行转换为字符串,其中(根据9.8)产生"null"(不是与toString混淆,这会产生"[object Window]"!)。

所以,我们考虑一下parseInt("null", 24)

当然,这不是一个完整的base-24数字字符串,但是“n”是:它是 decimal 23

现在,在拉出小数23之后解析停止,因为在base-24系统中找不到"u"

  

如果S包含任何字符   不是基数R数字,那么让Z成为   S的子串由全部组成   第一个这样的字符   字符;否则,让Z为S. [15.1.2.2/11]

(这就是为什么parseInt(null, 23)(和更低的基数)为您提供NaN而不是23:"n"不在base-23系统中。)

答案 2 :(得分:79)

Ignacio Vazquez-Abrams是正确的,但让我们看看how it works ......

来自15.1.2.2 parseInt (string , radix)

  

调用parseInt函数时   采取以下步骤:

     
      
  • 让inputString为ToString(string)。
  •   
  • 设S是一个新创建的inputString子串,由第一个组成   不是的角色   StrWhiteSpaceChar和所有字符   跟随那个角色。 (其他   单词,删除前导空格。)
  •   
  • 让签名为1。
  •   
  • 如果S不为空并且S的第一个字符是减号 - 那就让   标志为-1。
  •   
  • 如果S不为空且S的第一个字符是加号+或a   减号 - ,然后删除第一个   S的角色。
  •   
  • 设R = ToInt32(基数)。
  •   
  • 让stripPrefix为真。
  •   
  • 如果R≠0,则a。如果R< 2或R> 36,然后返回NaN。湾如果R≠16,那么   stripPrefix为false。
  •   
  • 否则,R = 0 a。设R = 10。
  •   
  • 如果stripPrefix为true,则a。如果S的长度至少为2而且   S的前两个字符也是   “0x”或“0X”,然后删除第一个   来自S的两个字符,让R = 16。
  •   
  • 如果S包含任何不是基数-R数字的字符,那么让Z为   S的子串由全部组成   第一个这样的字符   字符;否则,让Z为S.
  •   
  • 如果Z为空,则返回NaN。
  •   
  • 让mathInt为Z表示的数学整数值   在radix-R表示法中,使用字母   值为10的数字的A-Z和a-z   到(但是,如果R是10和​​Z.   包含20多个重要的   数字,后面的每个有效数字   20号可以用0位代替,   根据实施的选择;   如果R不是2,4,8,10,16或   32,那么mathInt可能是一个   依赖于实现的近似   到数学整数值   在radix-R中用Z表示   表示法。)
  •   
  • 设number为mathInt的Number值。
  •   
  • 返回标志×号码。
  •   
     

注意parseInt可能只解释一个   字符串的前导部分   整数值;它忽略了任何   无法解释的字符   作为整数表示法的一部分,   并没有任何迹象表明   这些字符被忽略了。

这里有两个重要的部分。我加粗了他们两个。首先,我们必须找出toString的{​​{1}}表示形式。我们需要在9.8.0节中查看null以获取该信息:

enter image description here

很好,所以现在我们知道在Table 13 — ToString Conversions内部产生一个toString(null)字符串。太好了,但它究竟如何处理在提供的基数范围内无效的数字(字符)?

我们在上面看'null',我们看到以下说法:

  

如果S包含任何字符   不是基数R数字,那么让Z成为   S的子串由全部组成   第一个这样的字符   字符;否则,让Z为S.

这意味着我们处理指定基数的所有数字并忽略其他所有数字。

基本上,执行15.1.2.2parseInt(null, 23)相同。 parseInt('null', 23)导致两个u被忽略(即使它们是基数23的一部分)。因此,我们只能解析l,使整个语句与n同义。 :)

无论哪种方式,很棒的问题!

答案 3 :(得分:33)

parseInt( null, 24 ) === 23

相当于

parseInt( String(null), 24 ) === 23

相当于

parseInt( "null", 24 ) === 23

基数24的数字是0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,...,n。

语言规范说

  
      
  1. 如果S包含任何不是基数-R数字的字符,则让Z为S的子字符串,由第一个这样的字符之前的所有字符组成;否则,让Z成为S.
  2.   

这是确保像15L这样的C风格整数文字正确解析的部分, 所以上面相当于

parseInt( "n", 24 ) === 23

"n"是上面数字列表的第23个字母。

Q.E.D。

答案 4 :(得分:16)

我猜null会转换为字符串"null"。因此n实际上是{base}中的23('base25'中相同'),{base}中的u无效,因此字符串null的其余部分将是忽略。这就是为什么它输出23直到u在'base31'中变为有效。

答案 5 :(得分:7)

parseInt使用字母数字表示,然后在base-24“n”中有效,但“u”是无效字符,那么parseInt只解析值“n”....

parseInt("n",24) -> 23

作为一个例子,试试这个:

alert(parseInt("3x", 24))

结果将是“3”。