var x = 010;
console.log(x); //8
JS引擎将数字x
转换为八进制数字。为什么会这样?我该如何预防?
我在这里的答案回答了这个问题,但这个问题并不完全是重复的,所以我包括我的答案的副本。
历史
问题是十进制整数文本不能有前导零:
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits(opt)
但是,ECMAScript 3 允许(作为可选扩展(解析以 8 为底 的前导零的文字:
OctalIntegerLiteral ::
0 OctalDigit
OctalIntegerLiteral OctalDigit
但是 ECMAScript 5 禁止在严格模式下这样做:
处理严格模式代码时的一致实现(请参阅 10.1.1(,不得扩展 NumericLiteral 的语法以包含 B.1.1 中所述的 OctalIntegerLiteral。
ECMAScript 6 引入了 BinaryIntegerLiteral 和 OctalIntegerLiteral,所以现在我们有了更连贯的文字:
- 二进制整数文字,前缀为
0b
或0B
。 - 八进制整数文字,前缀为
0o
或0O
。 - 十六进制整数文本,前缀为
0x
或0X
。
旧的 OctalIntegerLiteral 扩展已重命名为 LegacyOctalIntegerLiteral,在非严格模式下仍允许这样做。
结论
因此,如果要解析以 8 为基 数的数字,请使用 0o
或 0O
前缀(旧浏览器不支持(,或使用 parseInt
。
如果您想确保您的数字将以 10 为基数进行解析,请删除前导零或使用 parseInt
.
例子
-
010
- 在严格模式下(需要 ECMAScript 5(,它会抛出。
- 在非严格模式下,它可能会抛出或返回
8
(取决于实现(。
-
0o10
,0O10
- 在 ECMAScript 6 之前,他们抛出。
- 在 ECMAScript 6 中,它们返回
8
。
-
parseInt('010', 8)
- 它返回
8
.
- 它返回
-
parseInt('010', 10)
- 它返回
10
.
- 它返回
这是因为一些 JavaScript 引擎将前导零解释为八进制数字文字。它在 ECMAScript 规范的附录中定义。
但是,在严格模式下,符合标准的实现不能实现这一点 - 再次参见 ECMAScript 规范:
处理严格模式代码时的一致实现(请参阅 10.1.1(,不得扩展 NumericLiteral 的语法以包含 B.1.1 中所述的 OctalIntegerLiteral。
由于这种歧义,最好不要使用前导零。
JS仅当前导零的数字有效八进制时才将其视为八进制,如果不是,则将其视为十进制。为防止这种情况,请勿在源代码中使用前导零
console.log(010, 10, +"010")
if (021 < 019) console.log('Paradox');
或使用 strict mode
不允许使用前导零
'use strict'
if (021 < 019) console.log('Paradox');