イテレータ: for...of の裏側

配列やMapがfor...ofで使える仕組み。カスタムも作れる。

イテラブル
for...of で使えるオブジェクト。
イテレータ
next() を持つオブジェクト。
Symbol.iterator
イテレータを返すメソッドのキー。

イテレータ

本のしおり (Bookmark)

イテレータは「本のしおり」です。しおりは現在読んでいるページ(要素)を指しており、`next()` と言うたびに次のページに進み、その内容を読み上げます。本が終わると「もう終わりだよ(done: true)」と教えてくれます。

`for...of` ループの裏側で動いている仕組みです。配列や文字列はデフォルトで「イテラブル(繰り返し可能)」ですが、自分で作ったオブジェクトもイテレータを実装すれば `for...of` で回せるようになります。

Iterator Basics
// イテラブル = for...of で使える
const arr = [1, 2, 3];
for (const item of arr) {
console.log(item);
}
// イテレータを手動で使う
const iter = arr[Symbol.iterator]();
iter.next(); // { value: 1, done: false }
iter.next(); // { value: 2, done: false }
iter.next(); // { value: 3, done: false }
iter.next(); // { value: undefined, done: true }
// スプレッド構文もイテレータを使う
const copy = [...arr];
Bad
// ❌ Bad: インデックスでループ
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
Good
for...of
for (const item of arr) {
console.log(item);
}

パターン

Custom Iterables, Generators
// カスタムイテラブル
const range = {
from: 1,
to: 5,
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
return {
next() {
if (current <= last) {
return { value: current++, done: false };
}
return { done: true };
}
};
}
};
for (const n of range) {
console.log(n); // 1, 2, 3, 4, 5
}
// ジェネレータはイテレータを簡単に作れる
function* range(from, to) {
for (let i = from; i <= to; i++) {
yield i;
}
}
for (const n of range(1, 5)) {
console.log(n);
}
Tip: ジェネレータ関数を使えばイテレータを簡単に作れる。

合格ライン

for...of を使える
イテラブルとイテレータの違いを説明できる

演習課題

課題1: for...of
for...of でイテラブルをループしてください。
課題2: カスタムイテレータ
Symbol.iterator でカスタムイテレータを作成してください。