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

好的,所以我正在用parseInt搞乱它,看看它如何处理尚未初始化的值,并且我偶然发现了这个gem。 以下情况适用于24或以上的任何基数。

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

我在IE,Chrome和Firefox中测试了它们,并且它们都提醒了我们,所以我认为它一定在规范中。 快速谷歌搜索没有给我任何结果,所以我在这里,希望有人能解释。

我记得听过克罗克福德的演讲,他在那里说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是一个真实的陈述。


它将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

Mozilla告诉我们:

函数parseInt 将其第一个参数转换为一个字符串 ,解析它并返回一个整数或NaN。 如果不是NaN,则返回的值将是第一个参数的十进制整数表示形式,该形式以指定基数(base)中的数字形式表示。 例如,基数为10表示从十进制数,8个八进制数,16个十六进制数等转换而来。 对于10以上的基数,字母表中的字母表示数字大于9.例如,对于十六进制数字(基数为16),使用A到F.

在规范中,15.1.2.2/1告诉我们,使用内置的ToString来执行到字符串的转换,该内置的ToString (按照9.8)产生"null" (不要与toString混淆,这会产生"[object Window]" !)。

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

当然,这不是整个基数为24的数字字符串,但是“n”是:它是十进制的23。

现在,在十进制数字23被拔出后停止解析,因为在基本24系统中找不到"u"

如果S包含任何不是基数R数字的字符,则让Z为S的子串,包括第一个这样的字符之前的所有字符; 否则,让Z为S. [15.1.2.2/11]

(这就是为什么parseInt(null, 23) (和下面的radices)给你NaN而不是23的原因: "n"不在基-23系统中。)


伊格纳西奥巴斯克斯 - 艾布拉姆斯是正确的,但让我们看看它是如何工作的...

15.1.2.2 parseInt (string , radix)

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

  • 让inputString为ToString(string)。
  • 让S为新创建的inputString的子字符串,其中包含不是StrWhiteSpaceChar的第一个字符以及该字符后面的所有字符。 (换句话说,删除领先的空白区域。)
  • 让sign为1。
  • 如果S不是空的,并且S的第一个字符是负号 - ,让sign为-1。
  • 如果S不是空的,并且S的第一个字符是加号+或减号 - ,则从S中移除第一个字符。
  • 令R = ToInt32(基数)。
  • 让stripPrefix为true。
  • 如果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。
  • 让数学成为用Z表示的以数字-R表示的数学整数值,对于数值为10到35的数字使用字母AZ和az(但是,如果R是10并且Z包含超过20个有效数字,则每个重要数字如果R不是2,4,8,10,16或32,那么mathInt可能是一个依赖于实现的数学整数的近似值以R表示的Z值。)
  • 让number是mathInt的Number值。
  • 返回标志×号码。
  • 注意,parseInt可能仅将字符串的前导部分解释为整数值; 它会忽略任何不能被解释为整数表示的一部分的字符,并且没有指出任何这样的字符被忽略。

    这里有两个重要部分。 我粗体显示了他们两人。 所以首先,我们必须找出nulltoString表示是什么。 我们需要查看Table 13 — ToString Conversions的第9.8.0节中的信息:

    在这里输入图像描述

    太棒了,所以现在我们知道在内部做toString(null)产生一个'null'字符串。 好极了,但它究竟如何处理在提供的基数内无效的数字(字符)呢?

    我们看上面的15.1.2.2 ,我们看到下面的评论:

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

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

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

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

    链接地址: http://www.djcxy.com/p/94211.html

    上一篇: parseInt(null, 24) === 23... wait, what?

    下一篇: MySQL string replace