我在摆弄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]: 33,31:714695, 32:785077, 33:859935,34:939407,35:1023631, 36:1112745
博士tl;
解释为什么parseInt(null, 24) === 23是一个真语句。
Ignacio Vazquez-Abrams是正确的,但让我们看看它究竟是如何工作的……
从15.1.2.2 parseInt(字符串,基数):
When the parseInt function is called,
the following steps are taken:
Let inputString be ToString(string).
Let S be a newly created substring of inputString consisting of the first
character that is not a
StrWhiteSpaceChar and all characters
following that character. (In other
words, remove leading white space.)
Let sign be 1.
If S is not empty and the first character of S is a minus sign -, let
sign be −1.
If S is not empty and the first character of S is a plus sign + or a
minus sign -, then remove the first
character from S.
Let R = ToInt32(radix).
Let stripPrefix be true.
If R ≠ 0, then a. If R < 2 or R > 36, then return NaN. b. If R ≠ 16, let
stripPrefix be false.
Else, R = 0 a. Let R = 10.
If stripPrefix is true, then a. If the length of S is at least 2 and the
first two characters of S are either
“0x” or “0X”, then remove the first
two characters from S and let R = 16.
If S contains any character that is not a radix-R digit, then let Z be the
substring of S consisting of all
characters before the first such
character; otherwise, let Z be S.
If Z is empty, return NaN.
Let mathInt be the mathematical integer value that is represented by Z
in radix-R notation, using the letters
A-Z and a-z for digits with values 10
through 35. (However, if R is 10 and Z
contains more than 20 significant
digits, every significant digit after
the 20th may be replaced by a 0 digit,
at the option of the implementation;
and if R is not 2, 4, 8, 10, 16, or
32, then mathInt may be an
implementation-dependent approximation
to the mathematical integer value that
is represented by Z in radix-R
notation.)
Let number be the Number value for mathInt.
Return sign × number.
NOTE parseInt may interpret only a
leading portion of string as an
integer value; it ignores any
characters that cannot be interpreted
as part of the notation of an integer,
and no indication is given that any
such characters were ignored.
这里有两个重要的部分。我把它们都加粗了。首先,我们要找出null的toString表示是什么。我们需要查看9.8.0节中的表13 - ToString转换来获取信息:
很好,现在我们知道在内部做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)同义。:)
不管怎样,问得好!
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.