Welches der beiden folgenden Codefragmente (oder keines / beide) sollte in einer vollständigen Implementierung von ECMAScript 2015 funktionieren:
for (const e of a)
for (const i = 0; i < a.length; i += 1)
Nach meinem Verständnis sollte das erste Beispiel funktionieren, da e
es für jede Iteration initialisiert wird. Sollte dies nicht auch i
in der zweiten Version der Fall sein ?
Ich bin verwirrt, weil vorhandene Implementierungen (Babel, IE, Firefox, Chrome, ESLint) nicht konsistent zu sein scheinen und eine vollständige Implementierung const
mit verschiedenen Verhaltensweisen der beiden Schleifenvarianten aufweisen. Ich bin auch nicht in der Lage, einen konkreten Punkt im Standard zu finden, daher wäre das sehr dankbar.
javascript
for-loop
scope
const
ecmascript-6
adrianp
quelle
quelle
prefer-const
Option) und das zweite als ungültig. Die meisten Browser-Implementierungen betrachten beide Beispiele als ungültig.{const i = 0; while(i < a.length) { /* for body */ i += 1}}
Antworten:
Die folgende for-of-Schleife funktioniert:
for (const e of a)
Die ES6-Spezifikation beschreibt dies wie folgt:
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-in-and-for-of-statements-static-semantics-boundnames
Der Imperativ für die Schleife funktioniert nicht:
for (const i = 0; i < a.length; i += 1)
Dies liegt daran, dass die Deklaration nur einmal ausgewertet wird, bevor der Schleifenkörper ausgeführt wird.
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-statement-runtime-semantics-labelledevaluation
quelle
for
Schleife.const ...
ist kein Ausdruck. Sie müssen sich die Regel ansehenfor ( LexicalDeclaration Expression ; Expression) Statement
.const
s werden nicht pro Iteration neu deklariert.for (const e of a)
scheint in der neuesten Version von Firefox NICHT zu funktionieren. Ich bekommeSyntaxError: invalid for/in left-hand side
Ich werde die Spezifikation diesmal nicht zitieren, weil ich denke, dass es einfacher ist zu verstehen, was anhand eines Beispiels passiert.
Ist im Grunde gleichbedeutend mit
{ const __it = a[Symbol.iterator](); let __res; while ((__res = __it.next()) && !__res.done) { const e = __res.value; … } }
Der Einfachheit halber habe ich ignoriert, dass es eine TDZ mit
e
für dena
Ausdruck gibt, und die verschiedenen__it.return()
/__it.throw(e)
Aufrufe für den Fall, dass die Schleife vorzeitig (break
oderthrow
im Körper) beendet wird.ist im Grunde gleichbedeutend mit
{ const i = 0; while (i < a.length) { … i += 1; } }
Im Gegensatz dazu
let
wird eineconst
Deklaration in einerfor
Schleife nicht bei jeder Schleifeniteration neu deklariert (und der Initialisierer wird ohnehin nicht erneut ausgeführt). Wenn Sie nichtbreak
in der ersten Iteration, werden Siei +=
hier werfen.quelle
const
einenvar
ähnlichen Umfang hat und keine Zuweisung erfordert. Verwenden Sie den strengen Modus.while ( ( __res = __it.next() ) && !__res.done) {
. Andernfalls__res
endettrue
oderfalse
Ihr zweites Beispiel sollte definitiv nicht funktionieren, da
i
es einmal deklariert wird und nicht bei jeder Iteration. Dies ist nur eine Funktion der Funktionsweise dieser Kategorie von Schleifen.Sie können dies in einem normalen Browser versuchen:
for (var i = 0, otherVar = ""; i < [1,2,3,4].length; i += 1){ console.log(otherVar) otherVar = "If otherVar was initialized on each iteration, then you would never read me."; }
Es ist nicht der Fall, der
const
infor
Schleifen völlig unzulässig ist . Nurfor
das ändert const ist.Diese sind gültig:
for(const i = 0;;){ break } for(const i = 0; i < 10;){ break; }
Diese sind ungültig:
for(const i = 0;;){ ++i; break; } for(const i = 0;;++i){ if(i > 0) break; }
Ich bin mir nicht sicher, warum Firefox nach dem Lesen der ES2015-Spezifikation einen SyntaxError ausgibt (obwohl ich sicher bin, dass die cleveren Leute bei Mozilla korrekt sind), es scheint, als sollte dies eine Ausnahme auslösen:
quelle
const
aber nicht fürlet
?const
lässt sich nicht neu zuweisen (dies wird nicht bestritten) und zeigt in meinem Beispiel deutlich, wiefor
der variable Definitionsteil entgegen seinen impliziten Erwartungen funktioniert. Der Wert vonlet
kann geändert werden, entspricht funktionalvar
dem angegebenen Beispiel,let
ist jedoch nicht Teil der Frage.const i
nur einmal deklariert wird, aberlet i
nicht? Ihr Beispiel zeigt nur, wie esvar i
funktioniert, nichtconst i
. Da es ein klarer Unterschied zwischen istvar
,const
undlet
ich denke , unter Berufung auf ihn gegen specconst
wäre sehr wertvoll sein.const
Wert nur einmal zugewiesen werden. Ein erneuter Deklarationsversuch funktioniertconst
nicht. Mein Beispiel ist es, die Tatsache zu demonstrieren, dass die Deklaration nur einmal erfolgt und die Person, die die Fragen stellt, die Semantik von verstehtconst
.let
ist nicht das Problem, und nein, ich habe nicht explizit gemeint, was Sie vorschlagen, Sie haben falsch verstanden.let
, erhält jede Iteration eine eigene Kopie voni
.for(let foo = 0; i < 10; ++i){}
ist gleichbedeutend mit(funtion() { for(var i = 0; i < 10; ++i){ (function(i) { }(i)) } }());
Hier komme ich her:let
undconst
beide sind blockumfangig.for/in
undfor/of
das gleiche Verhalten fürconst
undlet
verfügbar machen, die normalefor
Schleife jedoch nicht. Es wird explizitconst
anders behandelt (verständlicherweise vielleicht). Sie sagen einfach, dass es "einmal deklariert" ist, aber das vereinfacht es zu sehr IMO.