TL;DR
由于前导 0,它被视为八进制(以 8 为底),就像前导 0x 将使其变为十六进制(以 16 为底)一样。这有着悠久而痛苦的历史,不再是现代 JavaScript 中八进制数的编写方式。在使用严格模式的现代 JavaScript 中,“遗留”八进制格式是语法错误;八进制数字以0o 前缀书写。
历史
早期(在 Netscape 的初始语言以及第一和第二个 ECMAScript 规范中),数字文字上的前导 0 正式表示 八进制(以 8 为基数),就像前导 @ 987654331@ 表示十六进制(以 16 为基数):
OctalIntegerLiteral ::
0 OctalDigit
OctalIntegerLiteral OctalDigit
例如,10、012 和 0xA 都是十进制数的写法。这与其他一些语法类似于 JavaScript(C、C++、Java...)的语言保持一致,但它非常令人困惑。
从 ECMAScript 3 开始,这种形式的八进制字面量被降级为可选扩展名,十进制整数字面量也发生了变化,因此它们不能有前导零(除非实现包含扩展名):
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits(opt)
但是ECMAScript 5 禁止在严格模式下这样做:
在处理 strict mode code (see
10.1.1) 时,符合规范的实现不得扩展 NumericLiteral 的语法以包含 OctalIntegerLiteral,如 B.1.1 中所述。
ECMAScript 6 (ECMAScript 2015) 引入了 BinaryIntegerLiteral 和 OctalIntegerLiteral,所以现在我们有了更多连贯的文字:
-
BinaryIntegerLiteral,前缀为
0b 或0B。
-
OctalIntegerLiteral,前缀为
0o 或0O。
-
HexIntegerLiteral,前缀为
0x 或0X。
旧的 OctalIntegerLiteral 扩展已重命名为 LegacyOctalIntegerLiteral,在非严格模式下仍然允许使用。
结论
因此,如果要解析以 8 为基数的数字,请使用 0o 或 0O 前缀(旧浏览器不支持),或使用 parseInt。
如果您想确保以 10 为基数解析您的数字,请删除前导零,或使用 parseInt。
示例
-
010
- 在严格模式下(需要 ECMAScript 5),这是一个语法错误。
- 在非严格模式下,可能是语法错误或返回
8(取决于实现)。
-
0o10, 0O10
- 在 ECMAScript 6 之前,它们是语法错误。
- 在 ECMAScript 6 中,它们返回
8。
-
parseInt('010', 8)
-
parseInt('010', 10)
如果你有兴趣,可以找到当前生活规范here,以及历史版本here。