Чому 019 не є синтаксичною помилкою JavaScript? Або чому 019> 020


78

Якщо я вводжу 019 > 020в консоль JavaScript (протестовано як у Chrome, так і у Firefox), я отримую відповідь true.

Це пояснюється 020інтерпретацією як OctalIntegerLiteral(рівних 16), тоді як 019, очевидно, інтерпретується як DecimalLiteral(і рівних 19). Як 19більше 16, 019 > 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насправді слід відхилити, я не розумію, чому це трактується як десяткове ціле число.

Я думаю, тут існує якесь правило сумісності, але мені не вдалося знайти офіційне визначення. Чи може хтось допомогти мені в цьому?

(Навіщо мені це потрібно: я розробляю синтаксичний аналізатор JavaScript / ECMAScript для Java з JavaCC і повинен звертати особливу увагу на специфікацію та її відхилення.)


3
019 + 0 == 19і 020 + 0 == 17тому він ігнорує початковий нуль, якщо він містить не восьмеричні цифри.
Регулярно

22
'use strict'; 019Цікавий факт: → SyntaxError: восьмеричні літерали та вісімкові екранні послідовності застаріли
goto-bus-stop

4
@Mathew: звичайно 020 + 0 ≠≠ 17:)
Jongware

4
@Mouser: не те саме, parseInt просто зупиняється на першому недійсному символі.
Jongware

2
@FelixKling, бо саме так формулюється виробництво. Або 0або NonZeroDigit DecimalDigits_opt. Якщо 0за чимсь слідує, це вже не так DecimalIntegerLiteral.
lexicore

Відповіді:


52

З того, що я міг знайти, здається, що деякі реалізації JavaScript просто не відповідають специфікаціям на цей момент.

З сайту MDN:

Зверніть увагу, що десяткові літерали можуть починатися з нуля (0), за яким слід інша десяткова цифра, але якщо наступна цифра після провідного 0 менша за 8, число аналізується як вісімкове число. Це не призведе до JavaScript, див. Помилку 957513 . Дивіться також сторінку про parseInt ().

Це все ще не пояснює, чому 019 == 19, враховуючи, що наступна цифра після провідного 0 дорівнює 1, і тому ціле число має бути проаналізовано як вісімкове. Але посилання на помилку, схоже, пов’язане з вашим випадком. В його описі сказано:

Наступна програма JavaScript повинна видавати помилку:

08

Відповідно до специфікації, DecimalIntegerLiteralніколи не може 0безпосередньо слідувати інша десяткова цифра, хоча Chrome / Opera, PrestOpera та Firefox це підтримують.

Помилка закрита як 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

Так 01само як і LegacyOctalLikeDecimalIntegerLiteral(3). Тоді 019є NonOctalDecimalIntegerLiteral(2), яке в свою чергу є DecimalIntegerLiteral(1).


2
Це правильна відповідь. Схоже, у Chrome є подібна проблема. Оцінка 019за врожайністю Spidermonkey 1: warning: 09 is not a legal ECMA-262 octal constant: 019. Здається, це було відхилено, оскільки існуючі (важливі) сайти зламалися.
Фелікс Клінг

2
Не впевнені, чому ви очікуєте 019бути восьмеричним літералом лише тому, що друга цифра - це 1? Звичайно, все, що містить 9не може бути восьмеричним ...
Бергі

2
@Bergi Я думаю, вам слід запитати про це хлопців з MDN, оскільки я не міг знайти жодного пункту в специфікації ECMAScript, який би виправдовував це тлумачення.
abl

4
Дивлячись на сканер синтаксичного аналізу V8, він дійсно припускає, що якщо число починається з 0, але має цифру 8 або 9, тоді число є десятковим (хоча коментар не пояснює, чому) github.com/v8/v8/blob/97757e2d8c5b706f1f642340a424b38e20022a2c/ ...
Віталій Федоренко

2
@VitaliiFedorenko Дуже вражений, як ти його викопав.
lexicore
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.