Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
この機能は広く実装されており、多くのバージョンの端末やブラウザーで動作します。2015年7月以降、すべてのブラウザーで利用可能です。
for 文は、括弧で囲みセミコロンで区切った 3 つの引数と、続いてループ内で実行される文(ふつうはブロック文)から成るループを構成します。
ループが始まる前に一度だけ評価される(代入式を含む)式または変数宣言。ふつうはカウンター変数を初期化するために使われます。この式では任意で、var キーワードを用いて新しい変数を宣言することもできます。var で宣言された変数はループ内のローカル変数にはなりません。すなわち、for ループが属するスコープと同じスコープになります。let で宣言された変数は文内のローカル変数になります。
この式の結果は捨て去られます。
condition 省略可ループのそれぞれの反復処理が行われる前に評価される式です。この式が true と評価された場合は、 statement が実行されます。この式が false と評価された場合は、実行は for 構造に続く最初の式に飛びます。
この条件テストはオプションです。省略した場合、この条件は常に true と評価されます。
afterthought 省略可ループのそれぞれの反復処理の最後に評価される式です。これは、次の condition の評価前に行われます。一般的には、カウンター変数を更新または増加するために使われます。
statement条件が true と評価された場合に限り実行される文です。ループ内で複数の文を実行するには、ブロック文を使用して文をグループ化してください。ループ内で文を実行しないようにするには、空文 (;) を使用してください。
他のループ文と同様に、statement 内部でフロー制御文が使用できます。
次の for 文は、変数 i を宣言し、それを 0 に初期化することから始まります。i が 9 より小さいことをチェックし、続く 2 つの文を実行し、ループを通過した後ごとに i を 1 増加します。
初期化ブロックは、式と変数宣言の両方を受け入れることができます。ただし、式には括弧で囲んでいない in 演算子を使用することができません。for...in ループと曖昧になるためです。
for ループの先頭にある 3 つの式は、省略可能です。例えば、initialization ブロックで変数を初期化する必要はありません。
initialization ブロックと同様に、condition ブロックも省略可能です。この式を省略した場合は、本体の中でループを脱出できるようにして、無限ループにならないようにしなければなりません。
3 つのブロックをすべて省略することもできます。繰り返しますが、 break 文を使用してループを終了させ、また break 文の条件がある時点で true になるように、変数を変更(増加)させていることを確認してください。
しかし、3 つの位置の式をすべて使用する訳ではない場合、特に最初の式で変数を宣言せず、上位のスコープで何かを変更している場合は、代わりに while ループを使用することを検討したほうが意図がより明確になります。
初期化ブロック内で変数を宣言する場合、上位のスコープで宣言する場合と異なる点があり、特にループ本体内でクロージャを作成する場合は重要です。例えば、下記のコードを見てください。
期待通り、0、1、2 とログ出力します。しかし、その変数が上位スコープで定義されている場合は、
3、3、3 とログ出力します。なぜかと言うと、それぞれの setTimeout が i 変数を閉じる新しいクロージャを作成しますが、i がループ本体のスコープでない場合、すべてのクロージャは最終的に呼び出されたときに同じ変数を参照します。そして setTimeout() の非同期であるため、すでにループが終了した後に実行され、すべてのキューのコールバック本体の i は 3 という値になります。
これは、初期化に var 文を使用した場合にも起こります。var で宣言された変数は関数スコープのみで、レキシカルスコープにならない(つまり、ループ本体のスコープにすることはできない)からです。
初期化ブロックのスコープ効果は、宣言がループ本体の中で行われ、たまたま condition と afterthought の部分でアクセス可能であるかのように理解することができます。より正確には、let宣言は for ループに特化されます。もし initialization が let 宣言であれば、ループ本体が評価された後、以下のことが毎回行われます。
そのため、afterthought 内で新しい変数を割り当てても、前回反復処理したときのバインディングには影響しません。
initialization の後、condition が初めて評価される直前に、新たな字句スコープも生成されます。これらの詳細はクロージャを作成することで観察可能であり、特定の時点でのバインディングを保持できます。例えば、このコードでは initialization 部分で生成されたクロージャは、afterthought 内での i の再代入によって更新されません。
これは、ループ本体の中で getI を宣言した場合のように "0, 1, 2" をログ出力するわけではありません。これは、getI が反復処理するたびに再評価されるのではなく、関数が一度作成され、(ループが最初に初期化されたときに宣言された変数を参照する)変数 i が閉じられるからです。その後、i の値を更新すると、実際には i という新しい変数が作成されますが、getI はそれを見ることができません。これを修正するには、i が更新されるたびに getI を再計算するようにします。
initialization 内の変数 i は、最初の反復を含む各反復内の i 変数とは別個の存在です。したがって、この例では、反復内の i の値が事前にインクリメントされているにもかかわらず、getI は 0 を返します。
実際、変数 i の最初のバインディングをキャプチャして、後でそれを割り当てることができます。この更新された値は、次の新しい i のバインディングを見るループ本体には見えません。
これは "0, 0, 0" とログ出力します。なぜなら、各ループ評価における i 変数は実際には別個の変数ですが、getI と incrementI はどちらも i の初期バインディングを読み書きし、その後に宣言されたものには対応しないからです。
以下の for の繰り返しでは、 final-expression 句の中でにおけるノードのオフセット位置を検索しています。 statement 節を使用する必要がない場合は、代わりにセミコロンを使用してください。
for 文の後のセミコロンは必須であることに注意してください。これは空文としての役割を果たすからです。そうしないと、for 文は以下の console.log 行を statement 節として取得し、log を複数回実行させることになる。
カンマ演算子を用いて、for ループで同時に更新される 2 つのカウンターを作成することができます。複数の let や var の宣言をカンマで結合することもできます。
| ECMAScript® 2027 Language Specification # sec-for-statement |
ブラウザー互換性一覧表を表示するには、JavaScript を有効にしてください。
より良いインターネットのための青写真。
このコンテンツの一部は、©1998–2026 個人の mozilla.org 協力者です。コンテンツはクリエイティブ・コモンズ・ライセンスのもとで利用できます。