Warum variieren die Ergebnisse je nach Platzierung der geschweiften Klammer?

118

Warum führen die folgenden Codefragmente aus diesem Artikel aufgrund nur einer einzigen Änderung der Platzierung von geschweiften Klammern zu unterschiedlichen Ergebnissen?

Wenn sich die öffnende geschweifte Klammer {in einer neuen Zeile befindet, test()kehrt sie zurück undefinedund in der Warnung wird "Nein - es ist gebrochen: undefiniert" angezeigt.

function test()
{
  return
  { /* <--- curly brace on new line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

Wenn sich die Klammer in derselben Zeile befindet wie return, wird test()ein Objekt zurückgegeben und "fantastisch" wird alarmiert.

function test()
{
  return { /* <---- curly brace on same line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

Nur lernen
quelle
Die Semi-Insertion-Semantik danach unterscheidet returnsich geringfügig von der an anderen Stellen, und ein Zeilenumbruch bedeutet an dieser Stelle "mehr" als "Midstream".
Dandavis

Antworten:

165

Dies ist eine der Gefahren von JavaScript: das automatische Einfügen von Semikolons. Zeilen, die nicht mit einem Semikolon enden, sondern das Ende einer Anweisung sein können, werden automatisch beendet, sodass Ihr erstes Beispiel effektiv so aussieht:

function test()
{
  return; // <- notice the inserted semicolon
  { 
    javascript: "fantastic"
  };
}

Siehe auch Douglas Crockfords JS-Styleguide , in dem das Einfügen von Semikolons erwähnt wird.

In Ihrem zweiten Beispiel geben Sie ein Objekt (das durch geschweifte Klammern gebildet wird) mit der Eigenschaft javascriptund ihrem Wert von zurück "fantastic", praktisch wie folgt:

function test() {
    var myObject = new Object();
    myObject.javascript = "fantastic";
    return myObject;
}
Residuum
quelle
5
Fun Fact: Bei einigen Engines können Sie die automatisch eingefügten Semikolons auskommentieren
Christopher Tarquini
1
@ ChrisT: Was? Welche? Wird das irgendwo erforscht?
Sean McMillan
1
@ SeanMcMillan Ich habe definitiv Artikel darüber gelesen, aber ich kann scheinbar keinen von ihnen aus einer Schnellsuche finden. Ich erinnere mich, dass das Setzen return /*und dann */{ das versteckte Semikolon in älteren Chromversionen effektiv auskommentieren würde. Ich
Christopher Tarquini
2
Aufgrund dieser Macken habe ich mir vor 10 Jahren ein Versprechen gegeben: Bleib weg vom Web! Ich betete, dass die Interwebs verschwinden würden ... Leider lief es nicht wie geplant, und jetzt muss ich mich auch mit diesen Problemen auseinandersetzen. Karma ist ab * tch :)
Jowen
1
Ich habe Leute gesehen, die religiös gegen Semikolons in JavaScript sind. Ich habe mich immer gefragt, was sie mit der zusätzlichen Zeit machen, die sie sparen, wenn sie keine Semikolons einfügen.
Iman Mohamadi
9

Javascript benötigt keine Semikolons am Ende von Anweisungen, aber der Nachteil ist, dass es erraten muss, wo sich die Semikolons befinden. Meistens ist dies kein Problem, aber manchmal erfindet es ein Semikolon, in dem Sie keines beabsichtigt haben.

Ein Beispiel aus meinem Blogbeitrag dazu ( Javascript - fast nicht zeilenbasiert ):

Wenn Sie den Code wie folgt formatieren:

function getAnswer() {
   var answer = 42;
   return
      answer;
}

Dann wird es so interpretiert:

function getAnswer() {
  var answer = 42;
  return;
  answer;
}

Die return-Anweisung hat ihre parameterlose Form und das Argument wird zu einer eigenen Anweisung.

Das gleiche passiert mit Ihrem Code. Die Funktion wird interpretiert als:

function test()
{
  return;
  {
    javascript : "fantastic"
  };
}
Guffa
quelle
3

Ich persönlich bevorzuge den Allman-Stil aus Gründen der Lesbarkeit (im Vergleich zum K & R-Stil).

Anstatt…

function test() {
  return {
    javascript : "fantastic"
  };
}

Ich mag…

function test() 
{
  var obj =
  {
    javascript : "fantastic"
  };

  return obj;
}

Aber das ist eine Umgehung. Ich kann aber damit leben.

Michael R.
quelle
3
Ich denke, wir sollten persönliche Vorlieben vermeiden, die vom Mainstream abweichen. Wir sollten den Entscheidungen der Mehrheit folgen, was die Konsistenz fördert und die Lesbarkeit erhöht
Jowen,
1
Ich finde seinen Code besser lesbar als den von K & R. Ziemlich subjektiv, wenn Sie "lesbar" meinen
Bran
Ich bevorzuge auch den Allman ... aber aufgrund von ASI lasse ich das Semi in derselben Zeile wie die Rückgabe, wenn ich ein Objekt zurückgeben muss. Ich bevorzuge dies, als eine "var x =" Zeile hinzuzufügen ...
Mik
1

Es ist, weil Javascript am häufigsten ";" Am Ende jeder Zeile, also im Grunde genommen, wenn Sie {in derselben Zeile zurückgegeben haben, sieht die Javascript-Engine, dass es etwas mehr geben wird, und wenn es in einer neuen Zeile steht, denkt sie, Sie hätten vergessen, ";" zu setzen, und setzt es für Sie.

Cichy
quelle
1
Ich verstehe nicht, warum die Antworten von Cichy, Darin und Ivo abgelehnt wurden?
BoltClock
1

Die geschweiften Klammern zeigen hier die Konstruktion eines neuen Objekts an. Ihr Code entspricht also:

function test() {
  var a = { javascript : "fantastic" };
  return a;
}

was funktioniert, wenn Sie schreiben:

function test() {
  var a = { javascript : "fantastic" };
  return; // ; is automatically inserted 
      a;
}

es funktioniert nicht mehr

Darin Dimitrov
quelle
0

Das Problem ist in der Tat die Semikoloninjektion wie oben beschrieben. Ich habe gerade einen guten Blogbeitrag zu diesem Thema gelesen. Es erklärt dieses Problem und vieles mehr über Javascript. Es enthält auch einige gute Referenzen. Sie können es hier lesen

Ivo van der Wijk
quelle
Ja, das habe ich auch gelesen, nach dem Lesen bitte ich hier, es durch Mastermind von js besser zu erklären.
JustLearn