javascript parseInt(null, 24) === 23...等等,什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6459758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 20:45:45  来源:igfitidea点击:

parseInt(null, 24) === 23... wait, what?

javascriptparseint

提问by Robert

Alright, so I was messing around with parseInt to see how it handles values not yet initialized and I stumbled upon this gem. The below happens for any radix 24 or above.

好的,所以我正在使用 parseInt 来查看它如何处理尚未初始化的值,我偶然发现了这个 gem。以下情况适用于任何基数 24 或以上。

parseInt(null, 24) === 23 // evaluates to true

I tested it in IE, Chrome and Firefox and they all alert true, so I'm thinking it must be in the specification somewhere. A quick Google search didn't give me any results so here I am, hoping someone can explain.

我在 IE、Chrome 和 Firefox 中对其进行了测试,它们都警告为 true,所以我认为它必须在规范中的某个地方。快速的谷歌搜索没有给我任何结果,所以我在这里,希望有人能解释一下。

I remember listening to a Crockford speech where he was saying typeof null === "object"because of an oversight causing Object and Null to have a near identical type identifier in memory or something along those lines, but I can't find that video now.

我记得听过 Crockford 的一次演讲,他说typeof null === "object"这是因为一个疏忽导致 Object 和 Null 在内存中具有几乎相同的类型标识符或类似的东西,但我现在找不到那个视频。

Try it: http://jsfiddle.net/robert/txjwP/

试试看:http: //jsfiddle.net/robert/txjwP/

EditCorrection: a higher radix returns different results, 32 returns 785077
Edit 2From zzzzBov: [24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745

编辑更正:更高的基数返回不同的结果,32 返回 785077
编辑 2来自 zzzzBov:[24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745



tl;dr

tl;博士

Explain why parseInt(null, 24) === 23is a true statement.

解释为什么parseInt(null, 24) === 23是真实的陈述。

回答by Ignacio Vazquez-Abrams

It's converting nullto the string "null"and trying to convert it. For radixes 0 through 23, there are no numerals it can convert, so it returns NaN. At 24, "n", the 14th letter, is added to the numeral system. At 31, "u", the 21st letter, is added and the entire string can be decoded. At 37 on there is no longer any valid numeral set that can be generated and NaN is returned.

它正在转换null为字符串"null"并尝试转换它。对于基数 0 到 23,没有它可以转换的数字,因此它返回NaN。在 24 处,"n"将第 14 个字母添加到数字系统中。在 31 处,"u"添加了第 21 个字母,并且可以解码整个字符串。在 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

回答by Lightness Races in Orbit

Mozilla tells us:

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.

函数 parseInt将它的第一个参数转换为 string,解析它,并返回一个整数或 NaN。如果不是 NaN,则返回值将是第一个参数的十进制整数表示,以指定基数(基数)为数字。例如,基数为 10 表示从十进制数、八进制 8、十六进制 16 等转换。对于大于 10 的基数,字母表中的字母表示大于 9 的数字。例如,对于十六进制数(基数为 16),使用 A 到 F。

In the spec, 15.1.2.2/1 tells us that the conversion to string is performed using the built-in ToString, which (as per 9.8) yields "null"(not to be confused with toString, which would yield "[object Window]"!).

规范中, 15.1.2.2/1 告诉我们使用内置的 执行到字符串的转换ToString,它(按照 9.8)产生"null"(不要与 混淆toString,它会产生"[object Window]"!)。

So, let's consider parseInt("null", 24).

所以,让我们考虑一下parseInt("null", 24)

Of course, this isn't a base-24 numeric string in entirety, but "n" is: it's decimal 23.

当然,这不是一个完整的 base-24 数字字符串,但 "n" 是:它是十进制 23

Now, parsing stops after the decimal 23 is pulled out, because "u"isn'tfound in the base-24 system:

现在,停止解析十进制23被拉出后,因为"u"没有在基本-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]

如果 S 包含任何不是基数-R 数字的字符,则让 Z 是 S 的子串,由第一个这样的字符之前的所有字符组成;否则,设 Z 为 S。 [15.1.2.2/11]

(And this is why parseInt(null, 23)(and lower radices) gives you NaNrather than 23: "n"is not in the base-23 system.)

(这就是为什么parseInt(null, 23)(和更低的基数)给你NaN而不是 23:"n"不在 base-23 系统中。)

回答by David Titarenco

Ignacio Vazquez-Abrams is correct, but lets see exactly how it works...

Ignacio Vazquez-Abrams 是正确的,但让我们看看如何工作的......

From 15.1.2.2 parseInt (string , radix):

来自15.1.2.2 parseInt (string , radix)

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.

调用 parseInt 函数时,采取以下步骤:

  • 令 inputString 为 ToString(string)。
  • 让 S 是 inputString 的一个新创建的子字符串,由第一个不是 StrWhiteSpaceChar 的字符和该字符之后的所有字符组成。(换句话说,删除前导空格。)
  • 令符号为 1。
  • 如果 S 不为空且 S 的第一个字符是减号 -,则令符号为 ?1。
  • 如果 S 不为空并且 S 的第一个字符是加号 + 或减号 -,则从 S 中删除第一个字符。
  • 让 R = ToInt32(基数)。
  • 让 stripPrefix 为真。
  • 如果R≠0,则a。如果 R < 2 或 R > 36,则返回 NaN。湾 如果 R ≠ 16,则令 stripPrefix 为假。
  • 否则,R = 0 让 R = 10。
  • 如果 stripPrefix 为真,则 a. 如果 S 的长度至少为 2 并且 S 的前两个字符是“0x”或“0X”,则从 S 中删除前两个字符并让 R = 16。
  • 如果 S 包含任何不是基数-R 数字的字符,则让 Z 是 S 的子串,由第一个这样的字符之前的所有字符组成;否则,令 Z 为 S。
  • 如果 Z 为空,则返回 NaN。
  • 设 mathInt 是由 Z 以基数 R 表示法表示的数学整数值,使用字母 AZ 和 az 表示值为 10 到 35 的数字。(但是,如果 R 为 10 且 Z 包含超过 20 个有效数字,则每个有效数字根据实现的选择,第 20 位之后的数字可以替换为 0 数字;如果 R 不是 2、4、8、10、16 或 32,则 mathInt 可能是数学整数的依赖于实现的近似值由 Z 以基数-R 表示法表示的值。)
  • 令 number 为 mathInt 的 Number 值。
  • 返回符号 × 数字。

注意 parseInt 只能将字符串的前导部分解释为整数值;它忽略任何不能被解释为整数符号的一部分的字符,并且没有给出任何此类字符被忽略的迹象。

There are two important parts here. I bolded both of them. So first of all, we have to find out what the toStringrepresentation of nullis. We need to look at Table 13 — ToString Conversionsin section 9.8.0 for that information:

这里有两个重要的部分。我加粗了他们两个。所以首先,我们必须找出toString表示的内容null是什么。我们需要Table 13 — ToString Conversions在第 9.8.0 节中查看该信息:

enter image description here

在此处输入图片说明

Great, so now we know that doing toString(null)internally yields a 'null'string. Great, but how exactly does it handle digits (characters) that aren't valid within the radix provided?

太好了,现在我们知道在toString(null)内部执行会产生一个'null'字符串。很好,但它究竟如何处理在提供的基数内无效的数字(字符)?

We look above to 15.1.2.2and we see the following remark:

我们往上看15.1.2.2,我们看到以下评论:

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.

如果 S 包含任何不是基数-R 数字的字符,则让 Z 是 S 的子串,由第一个这样的字符之前的所有字符组成;否则,令 Z 为 S。

That means that we handle all digits PRIOR to the specified radix and ignore everything else.

这意味着我们处理指定基数之前的所有数字并忽略其他所有数字。

Basically, doing parseInt(null, 23)is the same thing as parseInt('null', 23). The ucauses the two l's to be ignored (even though they ARE part of the radix 23). Therefore, we only can only parse n, making the entire statement synonymous to parseInt('n', 23). :)

基本上,做parseInt(null, 23)parseInt('null', 23). 将u导致两个l的被忽略(即使它们的基数23的一部分)。因此,我们只能解析n,使整个语句与 同义parseInt('n', 23)。:)

Either way, great question!

无论哪种方式,好问题!

回答by Mike Samuel

parseInt( null, 24 ) === 23

Is equivalent to

相当于

parseInt( String(null), 24 ) === 23

which is equivalent to

这相当于

parseInt( "null", 24 ) === 23

The digits for base 24 are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, ..., n.

基数 24 的数字是 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, ..., n。

The language spec says

语言规范说

  1. 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. 如果 S 包含任何不是基数-R 数字的字符,则让 Z 是 S 的子串,由第一个这样的字符之前的所有字符组成;否则,令 Z 为 S。

which is the part that ensures that C-style integer literals like 15Lparse properly, so the above is equivalent to

这是确保像 C 风格的整数文字15L正确解析的部分,所以上面的等价于

parseInt( "n", 24 ) === 23

"n"is the 23-rd letter of the digit list above.

"n"是上面数字列表的第 23 个字母。

Q.E.D.

QED

回答by Floern

I guess nullgets converted to a string "null". So nis actually 23in 'base24' (same in 'base25'+), uis invalid in 'base24' so the rest of the string nullwill be ignored. That's why it outputs 23until uwill become valid in 'base31'.

我猜null会被转换为 string "null"。所以n实际上23在'base24'中(在'base25'+中相同),u在'base24'中无效,因此字符串的其余部分null将被忽略。这就是为什么它输出23直到u将在“base31”中有效。

回答by fdaines

parseInt uses alphanumeric representation, then in base-24 "n" is valid, but "u" is invalid character, then parseInt only parses the value "n"....

parseInt 使用字母数字表示,然后在 base-24 "n" 是有效的,但 "u" 是无效字符,然后 parseInt 只解析值 "n"....

parseInt("n",24) -> 23

as an example, try with this:

举个例子,试试这个:

alert(parseInt("3x", 24))

The result will be "3".

结果将是“3”。