完全なECMAScript 2015実装で機能する必要があるのは、以下の2つのコードフラグメントのどちらか(または両方/両方ではない)です。
for (const e of a)
for (const i = 0; i < a.length; i += 1)
私の理解では、e
が各反復で初期化されるため、最初の例が機能するはずです。これは、2番目のバージョンのi
にも当てはまりませんか?
既存の実装(Babel、IE、Firefox、Chrome、ESLint)には一貫性がないようで、2つのループバリアントのさまざまな動作を伴うconst
の完全な実装があるため、混乱しています。また、標準の具体的なポイントを見つけることができないので、それは大歓迎です。
次のfor-ofループが機能します。
for (const e of a)
ES6仕様では、これについて次のように説明しています。
ForDeclaration:LetOrConst ForBinding
Forループの命令は機能しません。
for (const i = 0; i < a.length; i += 1)
これは、ループ本体が実行される前に宣言が一度だけ評価されるためです。
今回は仕様を引用しません。なぜなら、例によって何が起こるかを理解する方が簡単だと思うからです。
for (const e of a) …
基本的にと同等です
_{
const __it = a[Symbol.iterator]();
let __res;
while ((__res = __it.next()) && !__res.done) {
const e = __res.value;
…
}
}
_
簡単にするために、e
式にa
を含むTDZがあることと、その場合のさまざまな__it.return()
/__it.throw(e)
呼び出しを無視しました。ループは途中で終了します(本体のbreak
またはthrow
)。
for (const i = 0; i < a.length; i += 1) …
基本的にと同等です
_{
const i = 0;
while (i < a.length) {
…
i += 1;
}
}
_
let
とは対照的に 、const
ループ内のfor
宣言は、ループの繰り返しごとに再宣言されません(初期化子は再作成されません-とにかく実行されます)。最初の反復でbreak
をしない限り、_i +=
_はここにスローされます。
2番目の例は、i
が1回宣言されており、各反復でループのカテゴリがどのように機能するかの関数ではないため、確実に機能しません。
通常のブラウザでこれを試すことができます:
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.";
}
const
ループでfor
が完全に禁止されているわけではありません。 constを変更するのはfor
のみです。
これらは有効です:
for(const i = 0;;){ break }
for(const i = 0; i < 10;){ break; }
これらは無効です:
for(const i = 0;;){ ++i; break; }
for(const i = 0;;++i){ if(i > 0) break; }
FirefoxがES2015仕様を読んだ後にSyntaxErrorを返す理由はわかりません(Mozillaの賢い人は正しいと確信しています)が、例外を発生させることになっているようです:
環境レコードに新しいが初期化されていない不変のバインディングを作成します。文字列値Nは、バインドされた名前のテキストです。 Sがtrueの場合、初期化される前にバインディングの値にアクセスしようとするか、初期化後に設定すると、そのバインディングを参照する操作の厳密なモード設定に関係なく、常に例外がスローされます。 Sは、デフォルトでfalseに設定されるオプションのパラメーターです。