for...of

for...ofは、反復可能オブジェクト、たとえば組込みの String, Array, 配列風オブジェクト (例えば arguments や NodeList), TypedArray, Map, Set, およびユーザー定義の反復可能オブジェクトなどに対して、反復的な処理をするループを作成します。これはオブジェクトのそれぞれの識別可能なプロパティの値に対して、実行される文を表す独自の反復フックを呼び出します。

構文

for (variable of iterable) {
  statement
}
variable
反復処理の各回において、異なるプロパティの値が variable に割り当てられます。 variableconst, let, var で宣言することができます。
iterable
反復処理が行われる反復可能なプロパティを持つオブジェクトです。

Array での反復処理

const iterable = [10, 20, 30];

for (const value of iterable) {
  console.log(value);
}
// 10
// 20
// 30

letconst の代わりに使用しても、ブロック内で変数が再割り当てされます。

const iterable = [10, 20, 30];

for (let value of iterable) {
  value += 1;
  console.log(value);
}
// 11
// 21
// 31

String での反復処理

const iterable = 'boo';

for (const value of iterable) {
  console.log(value);
}
// "b"
// "o"
// "o"

TypedArray での反復処理

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() {
  for (const argument of arguments) {
    console.log(argument);
  }
})(1, 2, 3);

// 1
// 2
// 3

DOM コレクションでの反復処理

NodeList のような DOM コレクションでの反復処理です。次の例では、 read クラスを article の直下の子である段落に加えます。

// 注: これは以下のものに対応しているプラットフォームでのみ動作します。
// implemented NodeList.prototype[Symbol.iterator]
const articleParagraphs = document.querySelectorAll('article > p');

for (const paragraph of articleParagraphs) {
  paragraph.classList.add('read');
}

反復処理の終了

for...of ループ内では、 break, throw, return を発生させることで反復処理を中断させることができます。この場合、反復子は閉じられます。

function* foo(){ 
  yield 1; 
  yield 2; 
  yield 3; 
}; 

for (const o of foo()) { 
  console.log(o); 
  break; // 反復処理を閉じ、ループの外の実行が継続されます
}
console.log('done');

ジェネレーターでの反復処理

ジェネレーター、すなわち反復可能オブジェクトを生成する関数で反復処理することもできます。

function* fibonacci() { // ジェネレーター関数
  let [prev, curr] = [0, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (const n of fibonacci()) {
  console.log(n);
  // 1000で繰り返しを終了する
  if (n >= 1000) {
    break;
  }
}

ジェネレーターを再利用してはいけない

ジェネレーターは、 for...of ループが break キーワードなどで早く終了しても再利用してはいけません。ループを抜けると、ジェネレーターは閉じられ、そこで繰り返してもそれ以上の結果は算出されません。

const gen = (function *(){
  yield 1;
  yield 2;
  yield 3;
})();
for (const o of gen) {
  console.log(o);
  break;  // 反復処理を閉じる
}

// ジェネレーターを再利用してはいけません。以下の処理は意味がありません。
for (const o of gen) {
  console.log(o); // Never called.
}

イテレーターの同期

let range = {
  from: 1,
  to: 5,

  [Symbol.iterator]() {
    return {
      current: this.from,
      last: this.to,

      next() { // (2)
        if (this.current <= this.last) {
          return { done: false, value: this.current++ };
        } else {
          return { done: true };
        }
      }
    };
  }
};

for(let value of range) {
  console.log(value); // expected output: 1, then 2, then 3, then 4, then 5
}

その他の反復可能オブジェクトでの反復処理

明示的に iterable プロトコルを実装しているオブジェクトで反復処理することもできます。

const iterable = {
  [Symbol.iterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return { value: this.i++, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

for (const value of iterable) {
  console.log(value);
}
// 0
// 1
// 2

for...offor...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 (iterable.hasOwnProperty(i)) {
    console.log(i); // 0, 1, 2, "foo" と出力
  }
}

for (const i of iterable) {
  console.log(i); // 3, 5, 7 と出力
}

上記のコードをステップを追って見ていきましょう。

Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {}; 

const iterable = [3, 5, 7]; 
iterable.foo = 'hello';

すべてのオブジェクトは objCustom プロパティを継承し、すべての Array オブジェクトは arrCustom プロパティを継承します。 Object.prototypeArray.prototype にそれぞれこれらのプロパティを追加されているためです。オブジェクト iterableobjCustomarrCustom の各プロパティを、継承とプロトタイプチェーンによって継承しています。

for (const i in iterable) {
  console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom" と出力
}

このループは iterable オブジェクトの列挙可能なプロパティのみを、順序不定で出力します。配列の要素である 3, 5, 7hello は、列挙可能なプロパティではないため出力しません。実際、これらはプロパティではなく、値です。配列の添字arrCustomobjCustom と共に出力されます。なぜプロパティが反復処理に出てこないのかが分からない場合は、 array iteration and for...in にもっと詳しい説明があります。

for (const i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // 0, 1, 2, "foo" と出力
  }
}

このループは最初のものと似ていますが、 hasOwnProperty() を使用して見つかった列挙可能なプロパティがオブジェクト自身のものであるか、すなわち継承したものでないかどうかをチェックしています。オブジェクト自身のプロパティである場合は、ログ出力します。 0, 1, 2, foo は自身のプロパティである (継承されたものではない) ため出力されます。 arrCustomobjCustom継承されたものであるために出力されません。

for (const i of iterable) {
  console.log(i); // 3, 5, 7 と出力
}

このループは、 iterable反復可能なオブジェクトとして定義している順序でを反復処理し、ログ出力します。オブジェクトの要素である 3, 5, 7 は表示されますが、オブジェクトのプロパティは表示されません。

仕様書

仕様書 状態 備考
ECMAScript Latest Draft (ECMA-262)
for...of statement の定義
ドラフト
ECMAScript 2015 (6th Edition, ECMA-262)
for...of statement の定義
標準 初回定義

ブラウザーの互換性

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung InternetNode.js
for...ofChrome 完全対応 38Edge 完全対応 12Firefox 完全対応 13
補足
完全対応 13
補足
補足 Prior to Firefox 51, using the for...of loop construct with the const keyword threw a SyntaxError ("missing = in const declaration").
IE 未対応 なしOpera 完全対応 25Safari 完全対応 8WebView Android 完全対応 38Chrome Android 完全対応 38Firefox Android 完全対応 14
補足
完全対応 14
補足
補足 Prior to Firefox 51, using the for...of loop construct with the const keyword threw a SyntaxError ("missing = in const declaration").
Opera Android 完全対応 25Safari iOS 完全対応 8Samsung Internet Android 完全対応 ありnodejs 完全対応 あり
async iteratorsChrome 完全対応 63Edge 完全対応 12Firefox 完全対応 57IE 未対応 なしOpera 完全対応 50Safari ? WebView Android 完全対応 63Chrome Android 完全対応 63Firefox Android 完全対応 57Opera Android 完全対応 46Safari iOS ? Samsung Internet Android 完全対応 8.0nodejs ?
Closing iteratorsChrome 完全対応 51Edge 完全対応 14Firefox 完全対応 53IE 未対応 なしOpera 完全対応 ありSafari 完全対応 ありWebView Android 完全対応 ありChrome Android 完全対応 51Firefox Android 完全対応 53Opera Android 完全対応 ありSafari iOS 完全対応 ありSamsung Internet Android 完全対応 ありnodejs 完全対応 あり

凡例

完全対応  
完全対応
未対応  
未対応
実装状況不明  
実装状況不明
実装ノートを参照してください。
実装ノートを参照してください。

関連情報