好吧,所以我正在搞乱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
是真实的陈述。
答案 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
以获取该信息:
很好,所以现在我们知道在Table 13 — ToString Conversions
内部产生一个toString(null)
字符串。太好了,但它究竟如何处理在提供的基数范围内无效的数字(字符)?
我们在上面看'null'
,我们看到以下说法:
如果S包含任何字符 不是基数R数字,那么让Z成为 S的子串由全部组成 第一个这样的字符 字符;否则,让Z为S.
这意味着我们处理指定基数的所有数字并忽略其他所有数字。
基本上,执行15.1.2.2
与parseInt(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。
语言规范说
- 如果S包含任何不是基数-R数字的字符,则让Z为S的子字符串,由第一个这样的字符之前的所有字符组成;否则,让Z成为S.
醇>
这是确保像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”。