JavaScript には見た目のよく似た3つのループがあります。
- for ループ
- for in ループ
- for of ループ
どれも for
というキーワードを共通して使っているんですよね。
それぞれ違った場面で使うからこそループが3種類もあるはずですが、果たして違いはなんでしょう?
各ループの使い分け
- for ループ: 単純に指定回数だけ繰り返す
- for in ループ: オブジェクトに使う
- for of ループ: 配列や文字列など反復可能オブジェクトに使う
for ループ
まずは for ループの使い方を見てみましょう。
for (let count = 0; count <= 5; count++) {
console.log(count);
}
// > 0
// > 1
// > 2
// > 3
// > 4
// > 5
構文としては以下のようになっています。
for (初期化; 条件; 終わりの評価式) {
行う処理
}
- 初期化: カウンター変数の初期化
- 条件: 反復処理の前に評価され、true の場合に処理が実行される
- 終わりの評価式: 反復処理の後に毎回評価され、カウンター変数を更新する
決めた回数を繰り返すシンプルで使いやすいループなので、例えば配列の中身を列挙することもできます。
const arr = [1, 3, 5, 7];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
for in ループ
次に for in ループの使い方を見てみましょう。
for...in 文は、キーが文字列であるオブジェクトの列挙可能プロパティすべてに対して、継承された列挙可能プロパティも含めて反復処理を行います (Symbol がキーになったものは無視します)。
なにやら説明が難しいですが、オブジェクトに使うループです。
オブジェクトには「列挙可能プロパティ」というプロパティがあるのですが、これについては別の記事で触れているのでよければご覧ください。
const object = { a: 1, b: 2, c: 3 };
for (const key in object) {
const value = object[key]
console.log(`${key}: ${value}`);
}
// > "a: 1"
// > "b: 2"
// > "c: 3"
このように、 key
を羅列してくれるループです。
object[key]
の形にすることで value にもアクセスできます。
for of ループ
for of ループも見ていきましょう。
for...of 文は、反復可能オブジェクト、たとえば組込みの String, Array, 配列状オブジェクト (例えば arguments や NodeList), TypedArray, Map, Set, およびユーザー定義の反復可能オブジェクトなどに対して、反復的な処理をするループを作成します。
for of ループは「反復可能オブジェクト」を反復的に処理できます。
この反復可能オブジェクトというのがまた難しそうですが、使うのは配列と文字列、そして HTMLCollection などの DOM 関連のリストが多いでしょう。
const arr = ['a', 'b', 'c'];
for (const elm of arr) {
console.log(elm);
}
// > "a"
// > "b"
// > "c"
for in ループはオブジェクトの key に対して、つまりラベルの部分に対してループをしますが、 for of ループはラベルに当たるインデックス番号ではなく配列の要素そのものに対してループします。
文字列に対してループさせるとこのようになります。
const str = 'abc';
for (const elm of str) {
console.log(elm);
}
// > "a"
// > "b"
// > "c"
オブジェクトに無理やり for of ループを使ってみる
では反復可能オブジェクト専用の for of ループを無理やりオブジェクトに使ってみましょう。どうなるでしょう?
const object = { a: 1, b: 2, c: 3 };
for (const key of object) {
console.log(object[key]);
}
// > Uncaught TypeError: object is not iterable
TypeError となりました。やはり反復可能オブジェクトでなければ使えないようです。
配列に無理やり for in ループを使ってみる
逆パターンもやってみましょう。配列に対してオブジェクト用の for in ループを使います。
const arr = [1, 3, 5, 7];
for (const index in arr) {
console.log(index);
}
// > 0
// > 1
// > 2
// > 3
できるんかい!
なにが起こったかというと、インデックス番号が出力されました。
ということでこんなこともできます。
const arr = [1, 3, 5, 7];
for (const index in arr) {
console.log(arr[index]);
}
// > 1
// > 3
// > 5
// > 7
要素も表示できちゃうんですね。
それでは配列に対して for in ループを使ってもいいのでしょうか?
答えは No です。
オブジェクト用である for in ループには「順番」という概念がありません。
配列はインデックス番号で管理されていますね。
オブジェクトは何番の箱に何を入れた、という形では管理しづらい場合に名前をつけて管理するためのものです。つまり順番を持ちません。
配列に対して for in ループを使うと、せっかくインデックス番号という形で綺麗に順番を管理している配列をぐちゃぐちゃにしてしまう可能性があるのです。
配列、オブジェクトそれぞれの個性を活かすためループは使い分けるようにしましょう。
まとめ
- for ループ: 単純に指定回数だけ繰り返す
- for in ループ: オブジェクトに使う。配列にも使えるが順番の概念がないので非推奨
- for of ループ: 配列や文字列など反復可能オブジェクトに使う