为什么JavaScript将数字视为八进制,如果它具有前导零

Jag*_*sty 12 javascript

var x = 010;
console.log(x); //8
Run Code Online (Sandbox Code Playgroud)

JS引擎将数字x转换为八进制数.为什么会这样?我该怎样预防呢?

Ori*_*iol 10

我想我的答案在这里回答了问题,但问题并不完全重复,所以我附上了答案的副本.

历史

问题是十进制整数文字不能有前导零:

DecimalIntegerLiteral ::
    0
    NonZeroDigit DecimalDigits(opt)
Run Code Online (Sandbox Code Playgroud)

但是,ECMAScript 3允许(作为可选扩展)解析基数为8的前导零的文字:

OctalIntegerLiteral ::
    0 OctalDigit
    OctalIntegerLiteral OctalDigit
Run Code Online (Sandbox Code Playgroud)

ECMAScript 5禁止在严格模式下执行此操作:

一致性实现,在处理时严格模式代码(见10.1.1) ,必须不延伸的语法NumericLiteral包括OctalIntegerLiteral如描述B.1.1.

ECMAScript 6引入了BinaryIntegerLiteralOctalIntegerLiteral,所以现在我们有更多连贯的文字:

  • BinaryIntegerLiteral,前缀为0b0B.
  • OctalIntegerLiteral,前缀为0o0O.
  • HexIntegerLiteral,以0x或为前缀0X.

旧的OctalIntegerLiteral扩展已重命名为LegacyOctalIntegerLiteral,仍然允许在非严格模式下使用.

结论

因此,如果要解析基数为8的数字,请使用0o0O前缀(旧浏览器不支持)或使用parseInt.

如果您想确保您的数字将在基数10中解析,请删除前导零或使用parseInt.

例子

  • 010
    • 在严格模式下(需要ECMAScript 5),它会抛出.
    • 在非严格模式下,它可能会抛出或返回8(依赖于实现).
  • 0o10, 0O10
    • 在ECMAScript 6之前,他们会抛出.
    • 在ECMAScript 6中,他们返回8.
  • parseInt('010', 8)
    • 它回来了8.
  • parseInt('010', 10)
    • 它回来了10.