为什么019不是JavaScript语法错误?还是为什么019> 020


78

如果我输入019 > 020JavaScript控制台(在Chrome和Firefox中都经过测试),则会得到答案true

这是由于020被解释为OctalIntegerLiteral(等于16),而019显然是被解释为DecimalLiteral(等于19)。如19大于16019 > 020则为true

让我感到困惑的是为什么019将其解释为DecimalLiteral第一位。这是什么产品?DecimalIntegerLiteral不允许019

DecimalIntegerLiteral ::
    0
    NonZeroDigit DecimalDigits_opt

OctalIntegerLiteral也不允许019(因为9不是八进制数字):

OctalIntegerLiteral ::
    0 OctalDigit
    OctalIntegerLiteral OctalDigit

OctalDigit :: one of
    0 1 2 3 4 5 6 7

因此,从我在规范中看到的内容来看,019实际上应该拒绝它,我不明白为什么将其解释为十进制整数。

我猜这里有某种兼容规则,但是我没有找到正式的定义。可以请任何人帮助我吗?

(为什么需要这样做:我正在使用JavaCC开发JavaJavaScript / ECMAScript解析器,因此必须特别注意其规范-及其偏差。)


3
019 + 0 == 19020 + 0 == 17因此它忽略前导零,如果它包含非八进制数字。
Reactgular 2015年

22
有趣的事实:'use strict'; 019→SyntaxError:不建议使用八进制文字和八进制转义序列
goto-bus-stop

4
@Mathew:肯定会020 + 0 ≠≠ 17:)
Jongware

4
@Mouser:不是同一件事,parseInt只是在第一个无效字符处停止。
Jongware

2
@FelixKling因为这就是制作方式。无论是0NonZeroDigit DecimalDigits_opt。如果0后面有任何内容,则DecimalIntegerLiteral不再存在。
lexicore 2015年

Answers:


52

从我发现的情况来看,似乎JavaScript的某些实现并没有遵循这一点上的规范。

MDN站点:

请注意,十进制文字可以以零(0)开头,后跟另一个十进制数字,但是如果前导0之后的下一个数字小于8,则该数字将解析为八进制数字。这不会抛出JavaScript,请参见bug 957513。另请参见有关parseInt()的页面。

019 == 19鉴于前导0之后的下一个数字为1,因此整数仍应解析为八进制,但这仍然不能解释为什么。但是引用的错误似乎与您的情况有关。它的描述说:

以下JavaScript程序应引发错误:

08

根据规范,尽管Chrome / Opera,PrestOpera和Firefox支持,但DecimalIntegerLiteral绝对不能在0其后直接加上另一个十进制数字。

该错误已作为WONTFIX关闭

但是,019根据下一版的草稿,它将是有效的十进制文字,其值等于19。

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-additional-syntax-numeric-literals

(我已经标记了相关规则)

The syntax and semantics of 11.8.3 is extended as follows except that 
this extension is not allowed for strict mode code:

[...]

DecimalIntegerLiteral ::
    0
    NonZeroDigit DecimalDigits_opt
    NonOctalDecimalIntegerLiteral                         // (1)

NonOctalDecimalIntegerLiteral ::
    0 NonOctalDigit
    LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit    // (2)
    NonOctalDecimalIntegerLiteral DecimalDigit

LegacyOctalLikeDecimalIntegerLiteral ::
    0 OctalDigit                                          // (3)
    LegacyOctalLikeDecimalIntegerLiteral OctalDigit

所以,01LegacyOctalLikeDecimalIntegerLiteral(3)。然后019NonOctalDecimalIntegerLiteral(2),又是DecimalIntegerLiteral(1)。


2
这是正确的答案。Chrome似乎也有类似的问题。019用Spidermonkey产量进行评估1: warning: 09 is not a legal ECMA-262 octal constant: 019。似乎已被撤消,因为现有(重要)站点将中断。
Felix Kling 2015年

2
不知道为什么019只因为第二个数字是一个八进制字面量1?当然,任何包含9八进制的东西都不能是八进制的……
Bergi 2015年

2
@Bergi我想您应该向MDN的人员询问,因为我在ECMAScript规范中找不到任何可以证明这一解释的观点。
ABL

4
查看V8解析扫描器,它确实假定如果一个数字以0开头但具有8或9的数字,则该数字为十进制(没有评论解释为什么)github.com/v8/v8/blob/97757e2d8c5b706f1f642340a424b38e20022a2c/ …
Vitalii Fedorenko

2
@VitaliiFedorenko您对它的挖掘方式印象深刻。
lexicore
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.