前回は、配列を作って添字で取り出しました。 今回は全部の要素を順番に処理する方法です。
結論から言うと、ふだんは for...of を使ってください。 理由はこのあと説明します。
上のコードは書き換えて実行できます。fruits に要素を足してみてください。
3つの書き方
同じことを3通りで書きます。
出力は同じです。違うのは書き心地と、できることです。
| 添字が使えるか | 途中で抜けられるか | await で待てるか |
|
|---|---|---|---|
for |
使える | 抜けられる | 待てる |
for...of |
別に用意すれば使える | 抜けられる | 待てる |
forEach() |
使える(第2引数) | 抜けられない | 待てない |
途中で抜ける
条件に合ったところで止めたいことがあります。break を使います。
const nums = [1, 5, 8, 12, 3];
nums.forEach((n) => {
if (n > 10) return;
console.log(n);
});12 を見つけたところで止まったので、最後の 3 は見ていません。
その回だけ飛ばしたいときは continue です。
const ids = [1, 2, 3];
const load = async (id) => `データ${id}`;
ids.forEach(async (id) => {
const data = await load(id);
console.log(data);
});
console.log('ここが先に出てしまう');forEach は途中で抜けられない
ここが forEach() のいちばん大きな制限です。
const fruits = ['りんご', 'みかん'];
for (const i of fruits.keys()) {
console.log(typeof i, i);
}
for (const i in fruits) {
console.log(typeof i, i);
}return はそのコールバック関数から抜けるだけで、繰り返し自体は止まりません。
12 は飛ばされましたが、そのあとの 3 は出てしまいました。
forEach() の中に break は書けません。書くと構文エラーになります。
途中で抜けたいなら for...of を使ってください。
添字も欲しいとき
for...of だけでは添字が取れません。entries() を使うと添字と値の両方が取れます。
forEach() は第2引数で受け取れます。
待つ処理では forEach を使わない
時間のかかる処理を順番に待ちながら回したいとき、forEach() では待てません。
forEach() はコールバック関数の中の await を待ちません。
先へ進んでしまい、順序が崩れます。
for...of なら待てます。
このページの実行環境では、コードの一番外側でも await が書けます。
for...in を配列に使わない
名前が似ていますが、for...in はオブジェクトのキーを回すものです。
配列に使うと、添字が文字列で来ます。
'0' + 1 は '01' になるので、計算に使うと静かに壊れます。
配列には for...of を使ってください。
まとめ
- ふだんは
for...of。読みやすく、breakもawaitも使える - 添字が要るときは
entries()を足す forEach()は途中で抜けられず、await も待てないfor...inは配列向けではない
次に学ぶ
繰り返しながら新しい配列を作る書き方を学びます。
map() と filter() を使うと、ここまで書いてきたループの多くが1行になります。