在JavaScript中领先零
尝试这个:
<script language="javascript"> var iTest=040; alert(iTest); </script>
从什么时候开始是40 = 32?
前导零,数字被解释为八进制和4 * 8 = 32。
因为0
前缀表示八进制数(基数8)。
TL; DR
它被视为八进制数(基数为8),因为前导0
,就像前导的0x
会使其hex(基数为16)一样。 这有一个漫长而折磨的历史,不再是如何编写现代JavaScript的八进制数字。 在使用严格模式的现代JavaScript中,“传统”八进制格式是语法错误; 八进制数字是用0o
前缀编写的。
历史
早期(以Netscape的初始语言以及第一和第二ECMAScript规范),数字文本中的前导0
正式表示八进制 (基数为8),正如前导的0x
表示hex(基数为16):
OctalIntegerLiteral :: 0 OctalDigit OctalIntegerLiteral OctalDigit
例如, 012
和0xA
都是写十进制数的方法。 这与其他一些与JavaScript(C,C ++,Java,…)语法相似的语言保持一致,但是这种语言非常混乱。
从ECMAScript 3开始,八进制文本的forms被降级为一个可选的扩展,并且十进制整数文字被改变了,所以它们不能有前导零(除非实现包含扩展):
DecimalIntegerLiteral :: 0 NonZeroDigit DecimalDigits(opt)
但ECMAScript 5禁止在严格模式下执行此操作:
符合的实现在处理严格模式代码(见10.1.1)时 ,不得扩展NumericLiteral的语法,使其包含如B.1.1所述的OctalIntegerLiteral 。
ECMAScript 6 (ECMAScript 2015)引入了BinaryIntegerLiteral和OctalIntegerLiteral ,所以现在我们有更多连贯的文字:
- BinaryIntegerLiteral ,前缀为
0b
或0B
。 - OctalIntegerLiteral ,以
0o
或0O
为前缀。 - HexIntegerLiteral ,前缀为
0x
或0X
。
旧的OctalIntegerLiteral扩展名已经改名为LegacyOutIntegerLiteral ,但仍然允许在非严格模式下使用。
结论
因此,如果你想parsing一个基数为8的数字,可以使用0o
或0O
前缀(旧的浏览器不支持),或者使用parseInt
。
如果你想确保你的数字将以10为基础进行parsing,请删除前导零或使用parseInt
。
例子
-
010
- 在严格模式下(需要ECMAScript 5),这是一个语法错误。
- 在非严格模式下,可能是语法错误或返回
8
(实现相关)。
-
0O10
- 在ECMAScript 6之前,它们是语法错误。
- 在ECMAScript 6中,它们返回
8
。
-
parseInt('010', 8)
- 它返回
8
。
- 它返回
-
parseInt('010', 10)
- 它返回
10
。
- 它返回
如果你有兴趣,你可以在这里find当前的生活规范,以及这里的历史版本。