1. forEach とは?
forEach
は、JavaScript の配列や NodeList
、Map
、Set
などの反復可能なオブジェクトに対して、各要素に対して繰り返し処理を実行 できるメソッドです。
ポイント:通常の
for
ループと異なり、forEach
を使うと シンプルに記述 できますが、break
やreturn
でループを抜けることはできなくなります。
forEach を使用できるオブジェクトの例:
-
Array
(配列) -
NodeList
(querySelectorAll
の結果) -
Map
(キー
と値のペア
を保持するデータ構造) -
Set
(重複のない値
を保持するデータ構造) -
TypedArray
(型付き配列Uint8Array
など) -
Iterator
(2023年以降に追加)
Iterator.prototype.forEach は 2023 年以降に追加されたため、Iterator に対しても forEach を使用可能になりました。
補記:prototype とはオブジェクトの継承機能であり、特定のオブジェクトに共通のメソッドを提供する仕組みです。
例えば、Array.prototype.forEach は配列専用の forEach メソッドであり、Iterator.prototype.forEach はイテレーター専用の forEach メソッドを指します。
この仕組みのおかげで、オブジェクトごとに個別に forEach を定義するのではなく、prototype を利用して共通の機能を提供できます。
2. forEach
の基本構文
array.forEach((要素, インデックス, 配列) => {
// 繰り返し処理
});
-
要素
:現在の要素の値 -
インデックス
(省略可):現在の要素のインデックス(0 から始まる) -
配列
(省略可):元の配列全体
3. forEach
の基本的な使い方
例1:配列の各要素を表示
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => {
console.log(num);
});
//出力:
//1 2 3 4 5
例2:インデックスを含めて出力
const fruits = ["りんご", "バナナ", "ぶどう"];
fruits.forEach((fruit, index) => {
console.log(`${index}: ${fruit}`);
});
//出力:
//0: りんご
//1: バナナ
//2: ぶどう
4. forEach
の活用
querySelectorAll
との併用
querySelectorAll
は NodeList
を返しますが、forEach
を使ってループ処理が可能です。
const items = document.querySelectorAll(".item");
items.forEach(item => {
item.style.color = "red";
});
// すべての .item 要素の文字色を赤に変更
5. forEach
と for
ループの違い
比較項目 | forEach |
for ループ |
---|---|---|
記述の簡潔さ | ◎ 短く書ける | △ やや長くなる |
ループの途中終了 | ✖ break できない |
◎ break 可能 |
return の扱い |
✖ return できない |
◎ return 可能 |
例3:forEach
vs for
const numbers = [1, 2, 3, 4, 5];
// forEach(ループを途中で抜けられない)
numbers.forEach(num => {
if (num === 3) {
return; // ループは止まらない(単なる関数のreturnで、ループには影響しない)
}
console.log(num);
});
// 出力:
// 1
// 2
// 4
// 5
// for ループ(break で終了可能)
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] === 3) {
break; // ループ終了
}
console.log(numbers[i]);
}
// 出力:
// 1
// 2
6. map
との違い
forEach
と map
は似ていますが、map
は新しい配列を返す のに対し、forEach
は配列を変更せずに処理を実行します。
const numbers = [1, 2, 3, 4, 5];
// forEach(結果を返さない)
numbers.forEach(num => num * 2);
console.log(numbers); // [1, 2, 3, 4, 5]
// map(新しい配列を返す)
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
データを変換したいなら
map
、処理を実行するだけならforEach
7. Iterator.prototype.forEach
の登場(2023年以降)
これまで forEach
は Array
や NodeList
などに使われていましたが、2023 年以降 Iterator
にも forEach
メソッドが追加 されました。
Iterator.prototype.forEach
の特徴
- 逐次取得 するため、メモリ効率が良い(全データをメモリに展開しない)
-
Set.values()
やMap.keys()
などのイテレーターにも適用可能
コンソールで、
console.log(Array.prototype);
や
console.log(Iterator.prototype);
とすると、ArrayやIteratorが持っているメソッドを確認できる
8. Iterator(イテレーター)とは?
Iteratorとは、データを1つずつ順番に取得できるオブジェクトです。
.next() メソッドを持ち、データを逐次取得する仕組みを提供します。
Iteratorの基本的な動作
const iterator = [1, 2, 3][Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { done: true } // 処理が終了した合図
Iterator は .next() を使って順番に値を取得できる。
配列 や Set や Map はデフォルトで Iterator ではなく Iterable。 Iterator を取得するには Symbol.iterator を使う。
あるいは、array.values() や set.values()、map.keys() を使うと Iterator を取得できる。
const set = new Set(["a", "b", "c"]);
const iterator = set.values();
console.log(iterator.next()); // { value: "a", done: false }
Symbol.iterator を持つデータ型
以下のデータ型は Symbol.iterator を持っており、Iterator を作成できます。
-
Array
(配列) -
String
(文字列) -
Set
(集合) -
Map
(連想配列) -
arguments
(関数の引数オブジェクト) -
NodeList
(DOMの querySelectorAll などで取得されるリスト) -
TypedArray
(Uint8Array や Float32Array などの型付き配列)
Symbol.iterator を持つか確認する方法
console.log(typeof Array.prototype[Symbol.iterator]); // function
console.log(typeof String.prototype[Symbol.iterator]); // function
console.log(typeof Set.prototype[Symbol.iterator]); // function
console.log(typeof Map.prototype[Symbol.iterator]); // function
console.log(typeof arguments[Symbol.iterator]); // function(関数の中で確認)
console.log(typeof NodeList.prototype[Symbol.iterator]); // function(`querySelectorAll` で取得した要素群)
これらのオブジェクトは Symbol.iterator を持っているため、for...of や Iterator.prototype.forEach を適用可能!
9. Iterator.prototype.forEach
☑️ Iterator に forEach を使う
Iterator.prototype.forEach は、Iteratorの forEach
メソッド であり、Iterator に対して forEach を適用することができます。
const set = new Set(["apple", "banana", "cherry"]);
set.values().forEach(fruit => {
console.log(fruit);
});
// 出力:
// apple
// banana
// cherry
Set ではなく、Iterator に対して forEach を適用している!
逐次取得(1つずつ処理)するため、メモリ使用量を抑えられる!
10. Iterator.prototype.forEach の対応状況
Iterator.prototype.forEach は 比較的新しい技術(2023年以降) であり、すべてのブラウザでサポートされているわけではありません。
対応状況を確認するサイト
最新の対応状況は、以下のサイトで確認できます。
Iterator.prototype.forEach を使用する際は、古いブラウザでの動作に注意が必要です!
11. まとめ
☑️ forEach
は配列や NodeList
に対して 繰り返し処理 を適用できる
☑️ for
ループよりも 簡潔に書けるが、途中終了は不可
☑️ querySelectorAll
の NodeList
に対しても利用可能
☑️ map
との違いを理解し、適切に使い分ける
☑️ 2023 年以降 Iterator.prototype.forEach
が追加され、Iterator
にも forEach
を適用できるようになった
☑️ Iterator.prototype.forEach
はストリーム処理など、大量データを扱う場面で特に有効
☑️ Iterator.prototype.forEach は比較的新しい技術であり、古いブラウザでは対応していない可能性があるため注意!
forEach
を適切に活用し、効率的なループ処理を実装しよう!