Warum ist 019 kein JavaScript-Syntaxfehler? Oder warum ist 019> 020

78

Wenn ich 019 > 020die JavaScript-Konsole eingebe (sowohl in Chrome als auch in Firefox getestet), erhalte ich die Antwort true.

Dies ist darauf zurückzuführen, 020dass es als OctalIntegerLiteral(gleich 16) 019interpretiert wird, während es anscheinend als DecimalLiteral(und gleich 19) interpretiert wird . Da 19ist größer als 16, 019 > 020ist true.

Was mich verwundert ist, warum 019wird als DecimalLiteralan erster Stelle interpretiert . Um welche Produktion handelt es sich? DecimalIntegerLiteralerlaubt nicht 019:

DecimalIntegerLiteral ::
    0
    NonZeroDigit DecimalDigits_opt

OctalIntegerLiteralerlaubt auch nicht 019(da 9es sich nicht um eine Oktalstelle handelt):

OctalIntegerLiteral ::
    0 OctalDigit
    OctalIntegerLiteral OctalDigit

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

Von dem, was ich in der Spezifikation sehe, 019sollte eigentlich abgelehnt werden, ich verstehe nicht, warum es als Dezimalzahl interpretiert wird.

Ich denke, hier gibt es eine Art Kompatibilitätsregel, aber ich habe keine formale Definition gefunden. Könnte mir bitte jemand dabei helfen?

(Warum ich das brauche: Ich entwickle einen JavaScript / ECMAScript-Parser für Java mit JavaCC und muss besonders auf die Spezifikation und deren Abweichungen achten.)

Lexicore
quelle
3
019 + 0 == 19und 020 + 0 == 17so ignoriert es die führende Null, wenn sie nicht oktale Ziffern enthält.
Reactgular
22
'use strict'; 019Unterhaltsame Tatsache: → SyntaxError: Oktalliterale und Oktal-Escape-Sequenzen sind veraltet
gehe zur Bushaltestelle
4
@ Mathew: sicherlich 020 + 0 ≠≠ 17:)
usr2564301
4
@Mouser: Nicht dasselbe, parseInt stoppt nur beim ersten ungültigen Zeichen.
usr2564301
2
@FelixKling Weil so die Produktion formuliert ist. Entweder 0oder NonZeroDigit DecimalDigits_opt. Wenn 0etwas folgt, ist es nicht DecimalIntegerLiteralmehr.
Lexicore

Antworten:

52

Nach allem, was ich finden konnte, scheinen einige Implementierungen von JavaScript in diesem Punkt einfach nicht der Spezifikation zu folgen.

Von der MDN-Site:

Beachten Sie, dass Dezimalliterale mit einer Null (0) gefolgt von einer weiteren Dezimalstelle beginnen können. Wenn jedoch die nächste Ziffer nach der führenden 0 kleiner als 8 ist, wird die Zahl als Oktalzahl analysiert. Dies führt nicht zu JavaScript, siehe Fehler 957513 . Siehe auch die Seite über parseInt ().

Dies erklärt immer noch nicht, warum 019 == 19, da die nächste Ziffer nach der führenden 0 1 ist und die ganze Zahl daher als oktal analysiert werden sollte. Der Fehler, auf den verwiesen wird, scheint jedoch mit Ihrem Fall in Zusammenhang zu stehen. Die Beschreibung lautet:

Das folgende JavaScript-Programm sollte einen Fehler auslösen:

08

Gemäß der Spezifikation DecimalIntegerLiteralkann niemals 0direkt eine weitere Dezimalstelle folgen, obwohl Chrome / Opera, PrestOpera und Firefox dies unterstützen.

Der Fehler wird als WONTFIX geschlossen

Es 019wäre jedoch ein gültiges Dezimalliteral mit einem Wert von 19 gemäß dem Entwurf der nächsten Ausgabe:

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

(Ich habe die entsprechenden Regeln markiert)

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

So 01ist ein LegacyOctalLikeDecimalIntegerLiteral(3). Dann 019ist eine NonOctalDecimalIntegerLiteral(2), die wiederum eine DecimalIntegerLiteral(1) ist.

abl
quelle
2
Dies ist die richtige Antwort. Chrome scheint ein ähnliches Problem zu haben. Bewertung 019mit Spidermonkey-Erträgen 1: warning: 09 is not a legal ECMA-262 octal constant: 019. Es scheint, als wäre es zurückgesetzt worden, weil bestehende (wichtige) Websites kaputt gehen würden.
Felix Kling
2
Sie sind sich nicht sicher, warum Sie ein Oktalliteral erwarten würden 019, nur weil die zweite Ziffer eine ist 1? Sicherlich kann alles, was ein enthält, 9nicht oktal sein…
Bergi
2
@Bergi Ich denke, Sie sollten die Leute von MDN danach fragen, da ich in der ECMAScript-Spezifikation keinen Punkt finden konnte, der diese Interpretation rechtfertigt.
Abl
4
Mit Blick auf V8 - Scanner Parsen, nimmt in der Tat , dass , wenn eine Reihe beginnt mit 0 , aber eine Ziffer 8 oder 9 hat, dann ist die Zahl dezimal (kein Kommentar ist zu erklären , warum though) github.com/v8/v8/blob/97757e2d8c5b706f1f642340a424b38e20022a2c/ …
Vitalii Fedorenko
2
@VitaliiFedorenko Sehr beeindruckt, wie Sie es ausgegraben haben.
Lexicore