1. ホーム
  2. javascript

なぜ019はJavaScriptの構文エラーではないのですか?あるいは、なぜ 019 > 020 なのでしょうか?

2023-08-08 22:45:01

質問

もし私が 019 > 020 と入力すると (Chrome と Firefox の両方でテスト)、次のような答えが得られます。 true .

これは 020 として解釈されるためです。 OctalIntegerLiteral (イコール 16 ) 一方 019 と解釈されるようです。 DecimalLiteral (と解釈されるようです(そして、イコール 19 ). として 19 よりも大きいので 16 , 019 > 020true .

私が不思議に思うのは、なぜ 019 として解釈されるのか。 DecimalLiteral として解釈されます。どちらの演出なのでしょうか? DecimalIntegerLiteral が許さないのは 019 :

DecimalIntegerLiteral ::
    0
    NonZeroDigit DecimalDigits_opt

OctalIntegerLiteral もまた 019 (として 9 は8進数ではないため)。

OctalIntegerLiteral ::
    0 OctalDigit
    OctalIntegerLiteral OctalDigit

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

つまり、仕様書を見る限りでは 019 は実際には拒否されるはずで、10進数の整数として解釈される理由がわかりません。

私はここに何らかの互換性ルールがあると思いますが、正式な定義を見つけることができませんでした。どなたか、この件に関して私を助けていただけないでしょうか。

(なぜこれが必要なのか。を開発しています。 JavaCC を使って Java 用の JavaScript/ECMAScript パーサを開発しています。 を開発しており、その仕様とその逸脱に特別な注意を払う必要があります)。

どのように解決するのですか?

私が見つけたところでは、JavaScriptのいくつかの実装は、その点に関して仕様に従っていないだけのようです。

から MDN サイトから。

<ブロッククオート

10進数のリテラルは、0(ゼロ)で始まり、その後に別の10進数が続くことができることに注意してください。 しかし、先頭の 0 の次の桁が 8 より小さい場合、数値は 8 進数として解析されます。 が 8 より小さい場合、数値は 8 進数として解析されます。この場合 は JavaScript では投げません。 バグ 957513 . についてのページも参照してください。 のページも参照してください。

これはまだ、なぜ 019 == 19 は、先頭の 0 の次の桁が 1 であり、したがって全体の数は 8 進数として解析されるはずであることを考えると、これはまだ説明できません。しかし、参照されたバグはあなたのケースと関係があるようです。その説明にはこうあります。

以下のJavaScriptプログラムはエラーを投げるはずです。

08

仕様書の通り DecimalIntegerLiteral は決して 0 に直接 の後に別の小数点以下の数字が続くことはあり得ませんが、Chrome/Opera、PrestOpera, と Firefox はサポートしています。

このバグはWONTFIXとしてクローズされます。

しかし 019 は、次の版のドラフトによると、値が19に等しい有効な10進数リテラルになります。

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).