for...of と entries — 現代的なループのパターン
このトピックを終えると
for...of、for...in、forEach の違いを理解し、状況に応じて適切なループを選択できるようになります。
for...in は配列で使用しないでください
const fruits = ["apple", "banana", "cherry"];
for (const i in fruits) {
console.log(i); // "0", "1", "2" — インデックスが文字列
}for...in は オブジェクトのキー をイテレートします。配列で使用すると、インデックスを文字列として返します。プロトタイプチェーンのプロパティまでイテレートすることができ、予期しない結果になる可能性があります。
for...of は値をイテレートします
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
console.log(fruit); // "apple", "banana", "cherry"
}for...of は イテラブル (iterable) の値を直接イテレートします。配列、文字列、Map、Set などで使用できます。
for (const char of "hello") {
console.log(char); // "h", "e", "l", "l", "o"
}インデックスが必要な場合は entries()
for...of は値のみを返します。インデックスが必要な場合は、entries() を使用します。
const fruits = ["apple", "banana", "cherry"];
for (const [index, fruit] of fruits.entries()) {
console.log(`${index}: ${fruit}`);
}
// 0: apple
// 1: banana
// 2: cherry分割代入によって、インデックスと値を同時に取得します。Python の enumerate() と同様の役割を果たします。
forEach vs for...of
// forEach
fruits.forEach((fruit, index) => {
console.log(`${index}: ${fruit}`);
});
// for...of
for (const [index, fruit] of fruits.entries()) {
console.log(`${index}: ${fruit}`);
}どちらも似ていますが、重要な違いがあります。
forEach は 途中で停止できません。break と return は、ループ全体を中断しません ( return は現在のコールバックのみを終了します)。
// for...of — break 可能
for (const fruit of fruits) {
if (fruit === "banana") break;
console.log(fruit); // "apple" のみを出力
}
// forEach — break 不可
fruits.forEach(fruit => {
if (fruit === "banana") return; // このコールバックのみをスキップ
console.log(fruit); // "apple", "cherry" を出力
});途中で停止する必要がある場合は for...of、全体をイテレートする場合は forEach または map が適切です。
オブジェクトのイテレーション
通常のオブジェクトは、for...of で直接イテレートすることはできません。Object.entries() を使用します。
const user = { name: "Alice", age: 25, city: "Seoul" };
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
}
// name: Alice
// age: 25
// city: SeoulObject.keys() はキーのみを、Object.values() は値のみを返します。
重要なポイント
for...inはオブジェクトのキーを、for...ofはイテラブルの値をイテレートします。 配列でインデックスが必要な場合は、entries()を使用してください。 途中でbreakが必要な場合はfor...of、全体をイテレートする場合はforEachが適切です。