for...of
BaselineWidely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
for...of
文は、反復可能オブジェクトをソースとした一連の値を処理するループを実行します。反復可能オブジェクトには、たとえば組み込みのArray
,String
,TypedArray
,Map
,Set
,NodeList
(およびその他の DOM コレクション)、同様にarguments
オブジェクトや、ジェネレーター関数から生成されるジェネレーター、ユーザー定義の反復可能オブジェクトなどがあります。
試してみましょう
const array1 = ["a", "b", "c"];for (const element of array1) { console.log(element);}// Expected output: "a"// Expected output: "b"// Expected output: "c"
構文
for (variable of iterable) statement
解説
for...of
ループは、反復可能オブジェクトから取り出した値を 1 つずつ順次処理します。ループが値に対して行う各処理は反復処理と呼ばれ、ループは反復可能オブジェクトを反復処理すると言います。それぞれの反復処理では、現在のシーケンス値を参照する可能性のある文が実行されます。
for...of
ループが反復可能オブジェクトを反復処理する場合、最初にその反復可能オブジェクトの[Symbol.iterator]()
メソッドが呼び出されます。これはイテレーターを返すので、その返されたイテレーターのnext()
メソッドを呼び出すことで、variable
に代入される一連の値を生成することができます。
for...of
ループは、イテレーターが完全に処理された時点で終了します(next()
の結果は、done: true
を持つオブジェクトです)。他のループ文と同様に、フロー制御文をstatement
内部で使用することができます。
for...of
ループが早期に終了した場合(例えば、break
文に遭遇したり、エラーが発生した場合)、return()
のメソッドが呼び出されクリーンアップ処理が行われます。
for...of
のvariable
部分は、=
演算子の前に来ることができるものなら何でも受け入れることができます。const
を使用して、ループ本体の中で再代入されない変数を宣言することができます(反復処理間では変更できます。2 つの別個の変数として扱われるからです)。そうでない場合は、let
を使用してください。
const iterable = [10, 20, 30];for (let value of iterable) { value += 1; console.log(value);}// 11// 21// 31
メモ:反復処理ごとに新しい変数が作成されます。ループ本体内で変数を再代入しても、反復可能オブジェクト(この場合は配列)の元の値には影響しません。
構造分解を使用して複数のローカル変数に代入することもできますし、for (x.y of iterable)
のようなプロパティアクセサーを使用して、オブジェクトプロパティに値を代入することもできます。
しかし、特別なルールにより、変数名としてasync
を使用することは禁じられています。これは無効な構文です。
let async;for (async of [1, 2, 3]); // SyntaxError: The left-hand side of a for-of loop may not be 'async'.
これは、for
ループである有効なコードfor (async of => {};)
との構文のあいまいさを避けるためです。
例
Array に対する反復処理
const iterable = [10, 20, 30];for (const value of iterable) { console.log(value);}// 10// 20// 30
文字列に対する反復処理
文字列はUnicode コードポイント単位で反復処理します。
const iterable = "boo";for (const value of iterable) { console.log(value);}// "b"// "o"// "o"
型付き配列に対する反復処理
const iterable = new Uint8Array([0x00, 0xff]);for (const value of iterable) { console.log(value);}// 0// 255
Map に対する反復処理
const iterable = new Map([ ["a", 1], ["b", 2], ["c", 3],]);for (const entry of iterable) { console.log(entry);}// ['a', 1]// ['b', 2]// ['c', 3]for (const [key, value] of iterable) { console.log(value);}// 1// 2// 3
Set に対する反復処理
const iterable = new Set([1, 1, 2, 2, 3, 3]);for (const value of iterable) { console.log(value);}// 1// 2// 3
arguments オブジェクトに対する反復処理
arguments
オブジェクトで反復処理をすると、ある JavaScript 関数にすべての引数を渡すことができます。
function foo() { for (const value of arguments) { console.log(value); }}foo(1, 2, 3);// 1// 2// 3
NodeList に対する反復処理
ユーザー定義の反復可能オブジェクトに対する反復処理
独自のイテレーターを返す[Symbol.iterator]()
メソッドで、オブジェクトを反復処理します。
const iterable = { [Symbol.iterator]() { let i = 1; return { next() { if (i <= 3) { return { value: i++, done: false }; } return { value: undefined, done: true }; }, }; },};for (const value of iterable) { console.log(value);}// 1// 2// 3
オブジェクトを[Symbol.iterator]()
ジェネレーターメソッドで反復処理します。
const iterable = { *[Symbol.iterator]() { yield 1; yield 2; yield 3; },};for (const value of iterable) { console.log(value);}// 1// 2// 3
反復可能なイテレーター(this
を返す[Symbol.iterator]()
メソッドを持つイテレーター)は、for...of
などのイテレーターを想定した構文でイテレーターを使用可能にする、かなり一般的なテクニックです。
let i = 1;const iterator = { next() { if (i <= 3) { return { value: i++, done: false }; } return { value: undefined, done: true }; }, [Symbol.iterator]() { return this; },};for (const value of iterator) { console.log(value);}// 1// 2// 3
ジェネレーターに対する反復処理
function* source() { yield 1; yield 2; yield 3;}const generator = source();for (const value of generator) { console.log(value);}// 1// 2// 3
早期の脱出
最初のループでbreak
文を実行すると、ループが早期に終了します。イテレーターはまだ完了していないので、2 つ目のループは最初のループが停止したところから継続されます。
const source = [1, 2, 3];const iterator = source[Symbol.iterator]();for (const value of iterator) { console.log(value); if (value === 1) { break; } console.log("この文字列はログ出力されません。");}// 1// 同じイテレーターを使用する別のループは、// 最後のループが終わったところをピックアップします。for (const value of iterator) { console.log(value);}// 2// 3// イテレーターを使い切りました。// このループでは、反復処理は実行されません。for (const value of iterator) { console.log(value);}// [出力なし]
ジェネレーターはreturn()
メソッドを実装しており、ループが終了するとジェネレーター関数が早期復帰するように発生しています。このため、ジェネレーターはループをまたいで再利用することができません。
function* source() { yield 1; yield 2; yield 3;}const generator = source();for (const value of generator) { console.log(value); if (value === 1) { break; } console.log("この文字列はログ出力されません。");}// 1// イテレーターを使い切りました。// このループでは、反復処理は実行されません。for (const value of generator) { console.log(value);}// [出力なし]
for...of と for...in との違い
for...in
およびfor...of
文は、両方とも何かに対する繰り返しです。これらの主な違いは、何に対する繰り返しなのかというところです。
for...in
文は、オブジェクトのすべての列挙可能なプロパティに対して、順序不定で繰り返し処理を行います。for...of
文は、反復可能なオブジェクトが定義した順序で値を反復処理します。
次の例では、Array
に対してfor...of
ループとfor...in
ループを使用した場合の違いを示しています。
Object.prototype.objCustom = function () {};Array.prototype.arrCustom = function () {};const iterable = [3, 5, 7];iterable.foo = "hello";for (const i in iterable) { console.log(i);}// "0", "1", "2", "foo", "arrCustom", "objCustom"for (const i in iterable) { if (Object.hasOwn(iterable, i)) { console.log(i); }}// "0" "1" "2" "foo"for (const i of iterable) { console.log(i);}// 3 5 7
オブジェクトiterable
はobjCustom
およびarrCustom
プロパティを継承しています。Object.prototype
およびArray.prototype
の各プロパティを継承とプロトタイプチェーンで格納しているからです。
for...in
ループはiterable
オブジェクトの列挙可能なプロパティのみを出力します。配列の要素である3
,5
,7
や"hello"
は、列挙可能なプロパティではないため出力しません。これらは値です。配列の添字 がarrCustom
やobjCustom
と共に出力されます。なぜプロパティが反復処理に出てこないのかが分からない場合は、配列の反復処理とfor...in
にもっと詳しい説明があります。
2 番目のループは最初のものと似ていますが、Object.hasOwn()
を使用して見つかった列挙可能なプロパティがオブジェクト自身のものであるか、すなわち継承したものでないかどうかをチェックしています。オブジェクト自身のプロパティである場合は、ログ出力します。0
,1
,2
,foo
は自身のプロパティであるため出力されます。arrCustom
とobjCustom
は継承されたものであるために出力されません。
for...of
ループは、iterable
が反復可能オブジェクトとして定義している順序で値 を反復処理し、ログ出力します。オブジェクトの要素 である3
,5
,7
は表示されますが、オブジェクトのプロパティ は表示されません。
仕様書
Specification |
---|
ECMAScript® 2026 Language Specification # sec-for-in-and-for-of-statements |