Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

Сводка

Оператор for...of выполняет цикл обхода итерируемых объектов (включая ArrayMap, Set, объект аргументов и подобных), вызывая на каждом шаге итерации операторы для каждого значения из различных свойств объекта.

Синтаксис

for (переменная of объект)
  оператор
переменная
На каждом шаге итерации переменной присваивается значение нового свойства объекта.
объект
Объект, свойства которого обходятся во время выполнения цикла.

Примеры

 

 

Обход Array

let iterable = [10, 20, 30];

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

Можно также использовать const вместо let, если не нужно переназначать переменные внутри блока.

let iterable = [10, 20, 30];

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

Обход String

let iterable = 'boo';

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

Обход TypedArray

let iterable = new Uint8Array([0x00, 0xff]);

for (let value of iterable) {
  console.log(value);
}
// 0
// 255

Обход Map

let iterable = new Map([['a', 1], ['b', 2], ['c', 3]]);

for (let entry of iterable) {
  console.log(entry);
}
// ['a', 1]
// ['b', 2]
// ['c', 3]

for (let [key, value] of iterable) {
  console.log(value);
}
// 1
// 2
// 3

Обход Set

let iterable = new Set([1, 1, 2, 2, 3, 3]);

for (let value of iterable) {
  console.log(value);
}
// 1
// 2
// 3

Обход объекта arguments 

(function() {
  for (let argument of arguments) {
    console.log(argument);
  }
})(1, 2, 3);

// 1
// 2
// 3

Обход DOM коллекций

Обход DOM коллекций наподобие NodeList: следующий пример добавляет класс read параграфам, являющимся непосредственным потомкам статей:

 

// Примечание: работает только на платформах, где
// реализован NodeList.prototype[Symbol.iterator]
let articleParagraphs = document.querySelectorAll('article > p');

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

Закрытие итераторов

В циклах for...of  аварийный выход осуществляется через breakcontinuethrow или return. Во всех вариантах итератор завершается.

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

for (let o of foo()) { 
  console.log(o); 
  break; //  итератор закрывается, возврат
}

 

Обход генераторов

Вы можете выполнять обход генераторов, вот пример:

function* fibonacci() { // функция-генератор
    let [prev, curr] = [0, 1];
    for (;;) {
        [prev, curr] = [curr, prev + curr];
        yield curr;
    }
}

for (let n of fibonacci()) {
    // ограничивает последовательность на 1000
    if (n > 1000)
        break;
    console.log(n);
}

 

Не пытайтесь повторно использовать генератор

Генераторы нельзя использовать дважды, даже если цикл for...of  завершится аварийно, напр. через оператор break . При выходе из цикла генератор завершается и любые попытки получить из него значение обречены.

var gen = (function *(){
  yield 1;
  yield 2;
  yield 3;
})();
for (let o of gen) {
  console.log(o);
  break;  // Завешение обхода
}

// Генератор нельзя повторно обойти, следующее не имеет смысла!
for (let o of gen) {
  console.log(o); // Не будет вызван
}

Обход итерируемых объектов

Кроме того, можно сделать обход объекта явно реализующего iterable :

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

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

Различия между for...of и for...in

Оба оператора, и for...in и for...of производят обход объектов . Разница в том как они это делают.

Для for...in обход перечисляемых свойств объекта осуществляется в произвольном порядке.

Для for...of обход происходит в соответствии с тем, какой порядок определен в итерируемом объекте.

Следующий пример показывает различия в работе циклов for...of и for...in при обходе Array.

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

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

for (let i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs 0, 1, 2, "foo"
  }
}

for (let i of iterable) {
  console.log(i); // logs 3, 5, 7
}

Разберемся шаг за шагом в вышеописанном коде.

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

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

Каждый объект унаследует метод objCustom и каждый массив Array унаследует метод arrCustom благодаря созданию их в Object.prototype и Array.prototype. Объект iterable унаследует методы objCustom и arrCustom из-за наследования через прототип.

for (let i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom" 
}

Цикл выводит только перечисляемые свойства объекта iterable, в порядке их создания. Он не выводит значения 357 и hello поскольку они не являются перечисляемыми. Выводятся же имена свойств и методов, например arrCustom и objCustom. Если вы еще не совсем поняли по каким свойствам осуществляется обход, вот дополнительное объяснение того, как работает array iteration and for...in .

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs 0, 1, 2, "foo"
  }
}

Цикл аналогичен предыдущему, но использует hasOwnProperty() для проверки того, собственное ли это свойство объекта или унаследовано. Выводятся только собственные свойства. Имена 012 и foo принадлежат только экземпляру объекта (не унаследованы). Методы arrCustom и objCustom не выводятся поскольку они  унаследованы.

for (let i of iterable) {
  console.log(i); // logs 3, 5, 7 
}

Этот цикл обходит iterable и выводит те значения итерируемого объекта которые определены в способе его перебора, т.е. не свойства объекта, а значения массива 357 .

 

Спецификации

 

Спефицикация Статус Комментарий
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'for...of statement' в этой спецификации.
Стандарт Изначальное опеределение.
ECMAScript Latest Draft (ECMA-262)
Определение 'for...of statement' в этой спецификации.
Черновик  

 

Совместимость с браузерами

 

Update compatibility data on GitHub
КомпьютерыМобильныеServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidEdge MobileFirefox для AndroidOpera для AndroidiOS SafariSamsung InternetNode.js
Базовая поддержкаChrome Полная поддержка 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 Полная поддержка ДаEdge Mobile Полная поддержка 12Firefox 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 ? Firefox Полная поддержка 57IE ? Opera Полная поддержка 50Safari ? WebView Android Полная поддержка 63Chrome Android Полная поддержка 63Edge Mobile ? Firefox Android Полная поддержка 57Opera Android Полная поддержка 50Safari iOS ? Samsung Internet Android ? nodejs ?
Closing iteratorsChrome Полная поддержка 51Edge Полная поддержка ДаFirefox Полная поддержка 53IE Нет поддержки НетOpera Полная поддержка ДаSafari Полная поддержка ДаWebView Android Полная поддержка ДаChrome Android Полная поддержка ДаEdge Mobile Полная поддержка ДаFirefox Android Полная поддержка 53Opera Android Полная поддержка ДаSafari iOS Полная поддержка ДаSamsung Internet Android Полная поддержка Даnodejs Полная поддержка Да

Легенда

Полная поддержка  
Полная поддержка
Нет поддержки  
Нет поддержки
Совместимость неизвестна  
Совместимость неизвестна
Смотрите замечания реализации.
Смотрите замечания реализации.

 

Смотрите также

Метки документа и участники

Внесли вклад в эту страницу: becha, SphinxKnight, iomtt94, babichss, ZeroUnderscoreOu, BychekRU, dtretyakov
Обновлялась последний раз: becha,