parseInt(null, 24) === 23… wait, what?
好吧,所以我正在搞乱parseInt来看看它如何处理尚未初始化的值,我偶然发现了这个宝石。 对于任何24或以上的基数,都会发生以下情况。
1 | parseInt(null, 24) === 23 // evaluates to true |
我在IE,Chrome和Firefox中对它进行了测试,它们都是警告的,所以我认为它必须在某个地方的规范中。 一个快速的谷歌搜索没有给我任何结果所以我在这里,希望有人可以解释。
我记得听过Crockford演讲,他说
试一试:http://jsfiddle.net/robert/txjwP/
编辑校正:较高的基数返回不同的结果,32返回785077
编辑2来自zzzzBov:
TL;博士
解释为什么
它将
1 2 3 4 5 | js> parseInt(null, 36) 1112745 >>> reduce(lambda x, y: x * 36 + y, [(string.digits + string.lowercase).index(x) for x in 'null']) 1112745 |
Mozilla告诉我们:
function parseInt converts its first
argument to a string, parses it, and
returns an integer or NaN. If not NaN,
the returned value will be the decimal
integer representation of the first
argument taken as a number in the
specified radix (base). For example, a
radix of 10 indicates to convert from
a decimal number, 8 octal, 16
hexadecimal, and so on. For radices
above 10, the letters of the alphabet
indicate numerals greater than 9. For
example, for hexadecimal numbers (base
16), A through F are used.
在规范中,15.1.2.2/1告诉我们使用内置的
那么,让我们考虑一下
当然,这不是一个完整的base-24数字字符串,但是"n"是:它是十进制23。
现在,在拉出小数23之后解析停止,因为在base-24系统中找不到
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. [15.1.2.2/11]
(这就是为什么
Ignacio Vazquez-Abrams是正确的,但让我们看看它是如何工作的......
来自
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.
这里有两个重要的部分。我加粗了他们两个。首先,我们必须找出
很好,所以现在我们知道在内部执行
我们看上面
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.
这意味着我们处理指定基数之前的所有数字并忽略其他所有数字。
基本上,执行
无论哪种方式,很棒的问题!
1 | parseInt( null, 24 ) === 23 |
相当于
1 | parseInt( String(null), 24 ) === 23 |
这相当于
1 | parseInt("null", 24 ) === 23 |
基数24的数字是0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,...,n。
语言规范说
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.
这是确保像
所以上面相当于
1 | parseInt("n", 24 ) === 23 |
证明完毕
我猜
parseInt使用字母数字表示,然后在base-24"n"有效,但"u"是无效字符,那么parseInt只解析值"n"....
1 | parseInt("n",24) -> 23 |
例如,试试这个:
1 | alert(parseInt("3x", 24)) |
结果将是"3"。