Inwiefern unterscheidet sich Pythons Umgang mit Zeilenumbrüchen von den automatischen Semikolons in JavaScript?

41

Javascript hat eine Funktion namens "Automatisches Einfügen von Semikolons". Wenn der Parser auf ein ungültiges Token stößt und das letzte Token vor diesem Zeilenumbruch, fügt der Parser ein Semikolon an der Stelle ein, an der sich der Zeilenumbruch befindet. Auf diese Weise können Sie im Grunde Ihren gesamten Javascript-Code ohne Semikolon schreiben, müssen jedoch einige Randfälle berücksichtigen, vor allem, wenn Sie ein return-Schlüsselwort und dann den Wert haben, den Sie in einer neuen Zeile zurückgeben möchten.

function test(){
    // This will return 'undefined', because return is a valid statement
    // and  "john" is a valid statement on its own.
    return 
          "john"
}

Aufgrund dieser Fallstricke gibt es Dutzende von Artikeln mit Titeln wie "Automatisches Einfügen von Semikolons ist böse", "Verwenden Sie immer Semikolons in Javascript" usw.

Aber in Python verwendet niemand Semikolons und es hat genau die gleichen Fallstricke.

def test():
    # This will return 'undefined', because return is a valid statement
    # and  "john" is a valid statement on its own.
    return 
    "john"

Funktioniert genauso und doch hat niemand Todesangst vor Pythons Verhalten.

Ich denke, die Fälle, in denen sich das Javascript schlecht verhält, sind wenige genug, dass Sie sie leicht vermeiden können sollten. Rückgabe + Wert in einer neuen Zeile? Tun die Leute das wirklich oft?

Irgendwelche Meinungen? Verwenden Sie in Javascript Semikolons und warum?

Einar Egilsson
quelle
3
Es funktioniert nicht genau so. Die Semikoloneinfügung erfolgt nicht überall dort, wo sich der Zeilenumbruch in JavaScript befindet. Siehe das zweite Beispiel auf dieser Wikipedia-Seite . Das Semikolon wird in diesem Beispiel nicht an der Stelle eingefügt, an der sich der Zeilenumbruch befindet.
Reid
1
Mein Punkt war nicht, dass das Verwenden von Semikolons und nicht das Verwenden derselben genau gleich funktionierte. Der Punkt war, dass die Randfälle in Javascript und Python gleich waren. Es gibt sicherlich ein paar Randfälle, in denen Sie wissen müssen, was passiert. Bester Artikel, den ich zum Thema gelesen habe: inimino.org/~inimino/blog/javascript_semicolons
Einar Egilsson
4
Ich setze Semikolons in JavaScript aus dem gleichen Grund, aus dem ich Punkte in Sätzen verwende. Sicher, der Dolmetscher kann Ihre Aussagen normalerweise ohne sie verstehen, aber es ist nur eine schlechte Form.
JD Isaacks
3
Sie können in Ihren Beispielen auch gültiges Python schreiben. Der Kommentarindikator ist #nicht "//".
Aaron Dufour
2
"explizit ist immer besser als implizit"

Antworten:

62

Der Grund dafür ist, dass Zeilenumbrüche in Python eine eindeutige Methode zum Trennen von Codezeilen darstellen. Dies ist beabsichtigt und die Art und Weise, wie dies funktioniert, wurde gründlich durchdacht. Dadurch ist Python-Code perfekt lesbar und eindeutig, ohne spezielle End-of-Statement-Markierungen (mit Ausnahme der Newline).

Javascript wurde dagegen mit einer C-ähnlichen Syntax entworfen, bei der Anweisungen immer mit einem Semikolon abgeschlossen werden. Um die Fehlertoleranz der Sprache zu erhöhen, wird versucht zu erraten, wo zusätzliche Semikolons abgelegt werden müssen, um den Code zu korrigieren. Da dies auf die C-ähnliche Syntax nachgerüstet wurde, funktioniert es nicht immer wie erwartet (manchmal schätzt der Skript-Interpreter es falsch) und kann zu ziemlich kontraintuitivem Code führen.

Oder argumentieren mit "explizit ist besser als implizit": In Python ist eine neue Zeile bereits vollständig explizit, während sie in Javascript mehrdeutig ist. Fügen Sie daher das Semikolon hinzu, um sie explizit zu machen.

tdammers
quelle
3
Oh, und Sie können Code in Kommentare mit Anführungszeichen einfügen.
tdammers
1
Ein gutes Beispiel für einen Fall , in dem die automatischen Semikolon Einfügen unerwartete Sachen am Ende tut , ist dies: pastebin.com/aVeWGdya
HoLyVieR
5
In Python sind die Regeln ziemlich einfach: Anweisungen enden an Zeilenumbrüchen, es sei denn, es gibt eine nicht geschlossene mehrzeilige Zeichenfolge ("" ", '' '), ein nicht geschlossenes Diktat ({}), eine nicht geschlossene Liste ([]) oder einen umgekehrten Schrägstrich vor dem Zeilenumbruch In Javascript sind die Regeln deutlich komplizierter
Aaron Dufour
5
99% der Fehler abzudecken ist eine gute Möglichkeit, nur die wirklich schwer zu findenden Fehler zurückzulassen. Es ist in Ordnung, sie in Python zurückzulassen, da es einfache Regeln gibt, die 100% aller Probleme abdecken.
Aaron Dufour
1
@Aaron: Sie haben "einen nicht geschlossenen Satz von Klammern (())" vergessen. (Nicht unbedingt "ein nicht geschlossenes Tupel", da Klammern nicht nur für Tupel verwendet werden.)
JAB
28

Ich denke, es gibt einen ziemlich grundlegenden Unterschied zu der Art und Weise, wie es in Python funktioniert. Zitat aus dem Beitrag Einar Egilsson im Zusammenhang mit: "Ein Semikolon steht nicht am Ende einer Zeile, wenn das erste Token der folgenden Zeile als Teil derselben Anweisung analysiert werden kann."

In Python wird die Anweisung immer durch einen Zeilenumbruch beendet, außer in bestimmten, ziemlich offensichtlichen Fällen, z. B. in einem Ausdruck in Klammern. Andererseits versucht JavaScript, so viele Zeilen wie möglich zu analysieren, bevor die Anweisung beendet wird, was möglicherweise zu folgenden Ergebnissen führt:

// Define a function and name it area.
area = function(r) {
    return r * r * 3.14159
}

// Fooled you! We're actually invoking it.
(14)
Henrik
quelle
8
Hier ist eine lustige Wendung. Ersetzen Sie 14 durch so etwas wie (a + 1) ? do_something() : do_something_else();und plötzlich wird area auf den Rückgabewert von do_something()oder gesetzt do_something_else()und Sie bleiben stark verwirrt.
Reid
20

Ich minimiere meine JS-Dateien häufig im Produktionsmodus. Mittel zum Entfernen von Kommentaren und Zeilenumbrüchen.

Ohne die Verwendung von Semikolons würde dies mein Javascript beschädigen.

Deradon
quelle
8
OK, das ist gültig. Wenn es sich bei Ihrem Minimizer jedoch um einen tatsächlichen Parser handelt, kann er diese bei Bedarf erneut einfügen. Oder entfernen Sie die Zeilenumbrüche einfach nicht, => Sie behalten die Zeilenumbrüche bei, verlieren die Semikolons, sie sind ungefähr gleich groß, sodass nichts verloren geht.
Einar Egilsson
2
@ Einar Egilsson Closure Compiler macht das in der Tat.
Seriousdev
1
Wenn alle Dinge gleich sind, entspricht eine Newline der Anzahl der Bytes eines Semikolons. Ihr Minimierer entfernt möglicherweise alle neuen Zeilen, erfordert dann jedoch Semikolons. Es ist ein gleichmäßiger Austausch.
Logan Bailey
3
@Logan: Das setzt natürlich ein Byte Zeilenumbruch voraus ;-)
Cameron
1
Wenn wir Python anstelle von Javascript verwenden würden, müssten wir natürlich viel weniger codieren, um das Gleiche zu tun. Daher ist die Tatsache, dass Semikolons einige Bytes weniger als Einrückungen verwenden, umstritten.
BlueRaja - Danny Pflughoeft
5

Es funktioniert nicht so, wie Sie es beschreiben.

Javascript hat eine Funktion namens "Automatisches Einfügen von Semikolons". Wenn der Parser auf ein ungültiges Token stößt und das letzte Token vor diesem Zeilenumbruch, fügt der Parser ein Semikolon an der Stelle ein, an der sich der Zeilenumbruch befindet.

Das ist falsch. Beispiel:

return
  1 + 2;

1ist ein vollkommen gültiges Token, aber der Parser fügt direkt danach immer noch ein Semikolon ein return.

Wie Sie sehen, können Sie selbst nicht genau sagen, wo ein Semikolon passieren wird.

Das Problem beim automatischen Einfügen ist zweierlei:

  • Zum einen kann ein Semikolon weggelassen werden, bei dem das automatische Einfügen nicht bestimmen kann, dass ein Semikolon eingefügt werden muss.
  • Es kann auch vorkommen, dass ein Semikolon dort eingefügt wird, wo es nicht vorgesehen ist (siehe oben).

Die Verwendung von Semikolons nach jeder Anweisung hilft natürlich nur bei der ersten Fehlerquelle.

Auf jeden Fall halte ich das automatische Einfügen von Semikolons in C-ähnlicher Syntax für eine schlechte Idee.

Svante
quelle
1
Die ECMA-Skriptspezifikation gibt explizit an, in welchen Fällen ein Semikolon eingefügt wird, sodass Ihre Zeile "Sie können nicht genau sagen, wo ein Semikolon auftreten wird" nicht korrekt ist. Das Problem ist, dass es in einigen Fällen nicht intuitiv ist und es schwieriger ist, jemanden zu unterrichten, der nicht versteht, wie es funktioniert.
zzzzBov
1
@zzzzBov: Ja, es gibt eine genaue Spezifikation, aber hat jemand beim Codieren wirklich alle Fälle im Auge? Bist du sicher? Programmierer sind zu Recht faul; Sie wollen sich nicht an eine komplizierte Regel erinnern müssen, wenn eine viel einfachere dies tun würde. Also versuchen sie herumzukommen, sich daran erinnern zu müssen.
Svante
Ich stimme zu, dass das Einfügen eines Semikolons weitgehend unnötig ist. Ich sage nur, es gibt einen Unterschied zwischen der Aussage "Sie haben keine Ahnung, wohin die Semikolons führen" und "Die Spezifikation für das Einfügen von Semikolons ist ein nicht intuitives Durcheinander"
zzzzBov
1
@Svante: Aber das Rückgabebeispiel zeigt uns, dass wir diese Regeln sowieso kennen müssen. Dort haben Sie ein Semikolon verwendet, aber es hat Ihnen nicht geholfen, das zu tun, was Sie wollten. Da die Sprache über diese Funktion verfügt, haben wir die Möglichkeit, (1) überall Semikolons zu schreiben und die Regeln zu kennen, damit wir verstehen, was passieren wird. (2) nicht überall Semikolons zu schreiben und die Regeln zu verstehen, damit wir verstehen, was passieren wird. Angesichts dieser Wahl, denke ich, überspringe ich lieber die Semikolons
Einar Egilsson
4

Ich würde einen einfachen Grund nennen:

Javascript sieht "irgendwie Java-ish" oder "irgendwie C-ish". Natürlich ist es eine dynamische Sprache, also sieht es anders aus ... aber sei ehrlich - es gibt geschweifte Klammern. Sprachen mit geschweiften Klammern haben in der Regel Semikolons. Die natürlichen Reflexe treten ein und bringen Ihren Finger dazu, in Richtung der Semikolon-Taste zu gehen, bevor Sie schlagen Enter.

Python hingegen sieht schon auf den ersten Blick ganz anders aus. Daher wird intuitiv wenig oder gar keine Analogie zu "den langweiligen Standardsprachen" gebildet, und wenn man in den "Python-Modus" eintritt, kommt das Fehlen von Semikolons als natürlich heraus.

Kos
quelle
2

Es gibt eine Reihe von guten Gründen , die Semikoloneinfügung in JavaScript nicht zu verwenden.

Dies liegt in erster Linie daran, dass das Einfügen von Semikolons gemäß Definition im ECMAScript-Standard in einigen Fällen nicht intuitiv ist. @Svante weist auf einen Fall hin, bei returndem die Verwendung von Zeilenumbrüchen zu Problemen führt.

Was er nicht erwähnt ist , dass es zu Problemen führen werde , wenn Sie verwenden auch Semikolons, weil Semikolon Einfügen geschieht , ob Sie es wollen oder nicht.

Ein weiterer guter Grund , Semikolon-Einfügung nicht zu verwenden, ist die Ausgabesteuerung. In vielen Fällen wird JavaScript vor der Verwendung in der Produktion über einen Minifier ausgeführt. Einige Minifier verarbeiten möglicherweise Fälle mit automatischem Einfügen eines Semikolons, aber ich sehe keinen Grund, mich darauf zu verlassen, dass es perfekt funktioniert

Außerdem wird Inline-JavaScript für Content-Management-Systeme möglicherweise automatisch minimiert, und ich habe eine Reihe von Fällen erlebt, in denen der Auto-Minifier einfach Kommentare entfernt und Leerzeichen (einschließlich Zeilenumbrüche) am Anfang und Ende jeder Zeile entfernt.

Für Autoren, die nicht die Wahl haben, welche Tools ausgewählt werden, ist es viel einfacher, sich an ein Format zu halten, das in den allermeisten Fällen funktioniert.

zzzzBov
quelle
Ah, sorry, aber deinen dritten Absatz in Bezug auf , ich tun zu erwähnen , dass in meinem zweiten bis letzten Satz. :)
Svante
Ja, das Tooling-Problem ist gültig (obwohl gute Minifier damit umgehen sollten, z. B. Closure-Compiler). Aber meiner Meinung nach müssen wir diese Regeln trotzdem kennen, um Dinge wie das 'return'-Beispiel zu vermeiden. Und sobald ich die Regeln kenne, kann ich die Funktion auch verwenden, zumal der Code (IMO) dadurch besser lesbar wird.
Einar Egilsson
1

Das Nichtverwenden von Semikolon ist ein Rezept für einen Fehler, wenn Sie die JavaScript-Dateien Ihrer Dateien minimieren. Deshalb habe ich Angst davor.

Östlicher Mönch
quelle
1

In JavaScript können Sie ein Programm schreiben, das ohne das automatische Einfügen von Semikolons syntaktisch korrekt wäre, und ASI wandelt dieses Programm in ein anderes syntaktisch korrektes Programm um (z. B. Code, der einen Wert zurückgibt, in Code, der nichts zurückgibt). In Python gibt es keinen analogen Fall. In Python jede Newline , die können eine Erklärung enden wird am Ende eine Erklärung, es sei denn , es mit einem Backslash geschützt ist. Ich nehme an, dass die Regeln von Javascript ebenso deterministisch sind, aber ich weiß nicht, ob Sie die Regeln von Javascript zum Beenden von Anweisungen in einem einzigen Satz zusammenfassen können.

Ryan Thompson
quelle
1

In den meisten Fällen handhabt die ASI von JavaScript die Dinge wie erwartet. Ein Beispiel dafür, dass sich ASI möglicherweise nicht so verhält, wie Sie es erwarten:

var i = 0

(function() {
   // do something
})()

Dies wird so interpretiert, dass die Funktion 0mit der anonymen Funktion aufgerufen und dann das Ergebnis ausgeführt wird. In diesem Fall wollten Sie wahrscheinlich einen Auftrag ausführen und dann sofort die anonyme Funktion ausführen.

Für jemanden, der nicht mit ASI vertraut ist, kann es sehr verwirrend sein, wenn Sie auf solche Probleme stoßen. Daher empfehle ich Entwicklern in meinem Team immer, Semikolons zu verwenden.

(Nebenbei bemerkt: Ich benutze keine Semikolons, wenn ich an persönlichen / Nebenprojekten arbeite, weil ich weiß, dass niemand sonst den Code pflegen müsste.)

jay_soo
quelle
1

Wie Sie finde ich es ein bisschen paranoid. Die Regeln für das Einfügen von Semikolons sind in JavaScript genau wie in Python und CoffeeScript definiert. Niemand verunreinigt Python oder CoffeeScript mit Semikolons. Warum wird JavaScript also anders behandelt?

Ich denke, es ist eine Überreaktion auf den miserablen Zustand eines typischen JavaScript-Codes vor ungefähr zehn Jahren - JavaScript wurde als schwache, fehlerhafte, hässliche, nicht gute Sprache angesehen. Es war eine Verlegenheit. Sie könnten unmöglich guten Code in JavaScript schreiben!

Dann kamen die Leute zusammen und versuchte zu beweisen , dass Sie könnte schönen, klaren Code in JavaScript schreiben. Die Regel " Immer Semikolons verwenden" war Teil dieser Welle. Und um ehrlich zu sein, kann es einige Situationen etwas klarer machen.

Warum wird JavaScript immer noch anders behandelt?

Es gibt Trägheit. Und es sollte nicht übersehen werden, dass Menschen, die explizit strukturierten Code schätzen, häufig Sprachen im C-Stil bevorzugen. Menschen, die implizit strukturierten Code schätzen, wechseln häufig zu Sprachen, die nicht dem C-Stil entsprechen (wie z. B. CoffeeScript).

Schließung Cowboy
quelle
0

Ich benutze sie in Javascript ausschließlich aus Gründen der Konsistenz. Wenn die meisten Zeilen haben

Python hat sie für Randfälle wie mehrere Anweisungen in einer einzigen Zeile, Javascript hat sie und da Sie sie regelmäßig verwenden, halte ich mich an die Norm, in der sie verwendet werden.

Ich kann keine Verwendung für mehrere Anweisungen in derselben Zeile finden und sehe daher die Verwendung von Semikolons nicht vor.

Chris
quelle
Ja, ich habe das Python-Beispiel korrigiert. Aber der Punkt bleibt, Python hat auch Semikolons, Sie können sie gerne nach jeder Anweisung einfügen (und müssen, wenn Sie mehr als eine in jeder Zeile haben), aber die Leute benutzen sie nicht.
Einar Egilsson
0

Wenn Sie so etwas wie Bundle-Fu und Asset Manager für Ihre Web-App in Rails verwenden, würde dies fürchterlich scheitern, wenn am Ende des Tokens in Javascript kein Semikolon angezeigt wird. Es ist also eine gute Praxis, einen zu setzen.

subiet
quelle
Nun, die großen drei, YUI Compressor, Closure Compiler und UglifyJS, fügen alle Semikolons ein. Ich bin nicht überrascht, dass der Rubin-Port von JSMin Probleme hat.
Benjamin Atkin
0

Ich kann mich nicht erinnern, welche IE-Version genau verwendet wurde, aber es gibt Fälle, in denen der IE buchstäblich fehlerhaft ist, wenn ein Semikolon fehlt. IIRC ist, wenn Sie im globalen Bereich etwas haben wie:

var myFunc = function() {
  ...
}

Wenn Sie das nicht hinzufügen; Nach der schließenden Klammer schlägt das Programm in einigen IE-Versionen tatsächlich fehl. Dies und die anderen Gründe (einschließlich der Empfehlung von Crockford, sie immer explizit zu verwenden) haben mich veranlasst, sie in jedem Fall immer explizit zu verwenden.

Apinstein
quelle