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的前导部分解释为整数值; 它将忽略任何不能被解释为整数表示的一部分的字符,并且没有指出任何这样的字符被忽略。

这里有两个重要的部分。 我粗鲁的他们两个。 所以首先,我们必须找出nulltoString表示是什么。 我们需要查看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。

语言规范说

  1. 如果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”。