9

JS エディター ( Tern ) からコードを読んでいるときに、以下のスニペットに見られるように、for ループのさまざまな使用法に出くわしました。

コード スニペット 1 @行 463-468 :

for (;;) {
  /* some code */
}

コード スニペット 2 @行 97 ~ 100

for (var i = 0; ; ++i) {
  /* some code */
}

同じメモで、ボディが空の for ループにも出くわしました。

for (var p; p; p = someValue) /* empty body */ ;

コード実行フローで何が起こるかを理解しようとしています。

私の見解では、スニペット 1 のコードの場合、for ループには条件がないため、無限に続く可能性があります。スニペット 2 のコードでiは、無制限に継続的にインクリメントされますか? 3 番目のループは、?pに評価される何かが割り当てられるまで続きます。false

これらは私の頭の中にあるアイデアですが、まだ確信が持てません。手伝ってください。

4

2 に答える 2

5

要するに

まず第一に、あなたの主張はすべて正しいです。

  • 最初のループは、突然 (ブレーク、リターン、スローなどで) 終了するまで実行されます。
  • 2 番目のループは、突然終了するまで実行されますが、変数の割り当ても実行され、値がインクリメントされます。
  • 3 番目の for ループは、中央の条件が偽になるまで、通常の for ループのように実行されます。その体は空です。

しかし、なぜ JavaScript はこれを行うのでしょうか?

なぜこれが起こるのかを掘り下げてみましょう。

言語仕様を詳しく見てみると、次のことが for ループで発生することがわかります。

IterationStatement : for ( ExpressionNoIn(opt) ; Expression(opt) ; Expression(opt)) ステートメント

残りの回答では、これらのステートメントとその定義を扱います。

それでは、ケースを見てみましょう。

次のいずれfor(;;)かが発生した場合:

  • ExpressionNoIn が存在しないため、その節に対しては何も呼び出されません (節 1 に記載されているとおり)。

  • 2 番目の式は in ではないため、コールは返されません (第 3 節で述べられているように)。

  • 3 番目の式は空であるため、「インクリメント」は実行されません (3.f 節で述べているように)。

したがって、基本的には、予測どおりに無限に繰り返されます( abreakまたはから返される、またはからスローされるまで、および一般的に突然の完了を引き起こすものまで)。(節eとdが教えてくれるように)。

2 番目のケースfor (var i = 0; ; ++i)では、次のことが起こります。

  • ExpressionNoIn が存在するので、それを評価し、get value で割り当てます (1 節で述べているように)。私たちはそれを割り当てません。

  • 次に、2 番目の式がここにないため、無限に繰り返します。したがって、突然の実行が発生するか、ブレークが発生するまで続行します。具体的には、ここで定義されています。

  • i節 f が示すように、繰り返しごとにインクリメントします。

3 番目のケースfor (var p; p; p = someValue) /* empty body */ ;では、次のことが起こります。

これは for ループとして評価されます。ステートメントは確かに空ですが、for ループはあまり気にしません。唯一の違いは、for ループから値が返されないことです。基本的に、これは完全で正当な for ループです。;は単なる空のステートメントです。実際のループに内容のない for ループを実行したい場合に便利です。これは、機能検出で時々見られます。これは、... などの最小値を見つけたい場合にも役立ちnます。

値が falsey になるまで、またはより正確に呼び出すToBooleanと が生成さ falseれるまで実行されるという点で、あなたは正しいです。条項 3.a.ii が指定するとおり。

ご覧のとおり、これはすべて仕様にあり、明確に定義されています:)


コーダーはなぜこれを行うのですか?

最初のスニペットではbreakを使用してフロー制御を実行します。if (eol >= pos || eol < 0) break;(彼らは行末をチェックします。これは、より一般的な for ループで行うことができます)。

2 番目のスニペットでも、break を使用してフロー制御を行っています。

 if (!definitions.hasOwnProperty(uniq)) { name = uniq; break; }

彼らは再び for ループ内の break ステートメントに入れました。

3 番目のスニペットは文脈から外れていますが、(些細な例で) 10 より大きい最初の数値 (または 10 番目の div 要素、または文字列の出現 - おわかりのように) を見つけたいとしましょう。できること:

for(var i=0;i<=10;i++);

10 より大きい最初の数を取得します。

于 2013-08-05T13:36:17.480 に答える
1

あなたの理解は正しいです。

最初のスニペットは無限ループです。終了条件がないため、ループは (それ自体で) 永遠に続きます。これにはほぼ確実にbreak、本体内のどこかに、実行時にループを終了するステートメントが伴います。(もう 1 つのオプションは、スローされた例外がループを終了することですが、例外を制御フローとして使用することはお勧めできません。while (true) {...}) 通常、このパターン (または同等のパターン) は、終了条件が複雑すぎてループ ステートメント内で表現できない場合に発生します。

2 番目のスニペットは、終了条件がなければ永久に実行されるという点で、最初のスニペットに似ています。これにはbreak、ループを終了するためのステートメント (または例外) も必要です。ここでの唯一の違いは、カウンター変数も反復ごとにインクリメントされることです。

3 番目のスニペットは本体のないループですが、ループの反復ごとにテストと変数の更新が行われます。pご想像のとおり、これは が に評価されるまで続きますfalse。この for ループは、while ループ バージョンとまったく同じです。

var p;
while (p) {
    p = someValue;
}

おそらく、割り当てが まで繰り返し行われることがより明確になり!pます。

于 2013-08-05T13:37:59.380 に答える