parseInt(null,24)=== 23 …等等,什么?
好吧,所以我乱搞parseInt,看看它如何处理尚未初始化的值,我偶然发现这个gem。 以下情况适用于24或以上的任何基数。
parseInt(null, 24) === 23 // evaluates to true
我在IE浏览器,Chrome浏览器和火狐浏览器中进行了testing,他们都警惕,所以我认为它必须在规范的地方。 快速谷歌search没有给我任何结果,所以我在这里,希望有人能解释。
我记得听过克罗克福德的演讲,他说typeof null === "object"
因为一个疏忽导致对象和空有一个接近相同types的标识符在内存或沿着这些线,但我找不到那个video现在。
试试看: 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
转换为string"null"
并尝试将其转换。 对于基数0到23,没有可以转换的数字,所以它返回NaN
。 在24位,第14个字母"n"
被添加到数字系统中。 在31,添加第21个字母"u"
,整个string可以被解码。 在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 将其第一个参数转换为一个string ,parsing它,并返回一个整数或NaN。 如果不是NaN,则返回值将是以指定基数(base)中的数字forms表示的第一个参数的十进制整数表示forms。 例如,基数10表示从十进制数,8个八进制数,16个hex数等转换而来。 对于高于10的基数,字母表中的字母表示大于9的数字。例如,对于hex数字(基数为16),使用A到F.
在规范中 ,15.1.2.2/1告诉我们,使用内置的ToString
来执行到string的转换,(根据9.8)产生"null"
(不要与toString
混淆,这会产生"[object Window]"
!)。
所以,让我们考虑parseInt("null", 24)
。
当然,这不是一个完整的基数为24的数字string,但“n”是: 十进制数字23 。
现在,在小数点后的parsing停止,因为在基本24系统中找不到"u"
:
如果S包含任何不是基-R数字的字符,则设Z是由第一个这样的字符之前的所有字符组成的S的子string; 否则,让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是一个新创build的inputString的子string,它由不是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的长度至less为2,并且S的前两个字符是“0x”或“0X”,则从S中移除前两个字符并让R = 16。
- 如果S包含任何不是基-R数字的字符,则设Z是由第一个这样的字符之前的所有字符组成的S的子string; 否则,让Z为S.
- 如果Z为空,则返回NaN。
- 让math成为以Z表示的math整数值,用基数R表示法,对于数字10到35的数字使用字母AZ和az(但是,如果R是10并且Z包含超过20个有效数字,则每个重要数字如果R不是2,4,8,10,16或32,那么mathInt可能是实现依赖于math整数的近似值由R表示的值,以R表示。)
- 让number是mathInt的Number值。
- 返回标志×号码。
注意,parseInt可能仅将string的前导部分解释为整数值; 它将忽略任何不能被解释为整数表示的一部分的字符,并且没有指出任何这样的字符被忽略。
这里有两个重要的部分。 我粗鲁的他们两个。 所以首先,我们必须找出null
的toString
表示是什么。 我们需要查看Table 13 — ToString Conversions
在9.8.0节中的信息:
太棒了,所以现在我们知道在内部做toString(null)
产生一个'null'
string。 很好,但是它究竟如何处理在提供的基数内无效的数字(字符)呢?
我们看上面的15.1.2.2
,我们看到下面这句话:
如果S包含任何不是基-R数字的字符,则设Z是由第一个这样的字符之前的所有字符组成的S的子string; 否则,让Z为S.
这意味着我们将所有数字处理为指定的基数前的所有数字,并忽略其他一切。
基本上, parseInt(null, 23)
和parseInt('null', 23)
。 u
会忽略这两个l
(即使它们是基数23的一部分)。 因此,我们只能parsingn
,使得整个语句与parseInt('n', 23)
同义。 🙂
无论哪种方式,很好的问题!
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的子string; 否则,让Z为S.
这是保证像15L
这样的C样式整数文字parsing得当的部分,所以上面相当于
parseInt( "n", 24 ) === 23
"n"
是上面数字列表的第23个字母。
QED
我猜null
被转换为一个string"null"
。 所以n
在'base24'中实际上是23
(在'base25'+中是一样的), u
在'base24'中是无效的,所以stringnull
的其余部分将被忽略。 这就是为什么它输出23
直到u
将在“base31”有效。
parseInt使用字母数字表示,那么在base-24中,“n”是有效的,但是“u”是无效的字符,那么parseInt只能分析值“n”….
parseInt("n",24) -> 23
作为一个例子,试试这个:
alert(parseInt("3x", 24))
结果将是“3”。