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
,Map
,Set
, объектаргументов и подобных), вызывая на каждом шаге итерации операторы для каждого значения из различных свойств объекта.
Синтаксис
Примеры
Обход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
аварийный выход осуществляется черезbreak
,throw
или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); // выведет 0, 1, 2, "foo", "arrCustom", "objCustom"}for (let i in iterable) { if (iterable.hasOwnProperty(i)) { console.log(i); // выведет 0, 1, 2, "foo" }}for (let i of iterable) { console.log(i); // выведет 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); // выведет 0, 1, 2, "foo", "arrCustom", "objCustom"}
Цикл выводит толькоперечисляемые свойства объектаiterable
, в порядке их создания. Он не выводитзначения3
,5
,7
иhello
поскольку онине являются перечисляемыми, фактически они вообще не являются свойствами, они являютсязначениями. Выводятся жеимена свойств и методов, напримерarrCustom
иobjCustom
. Если вы ещё не совсем поняли, по каким свойствам осуществляется обход, вот дополнительное объяснение того, как работаетarray iteration and for...in
.
for (let i in iterable) { if (iterable.hasOwnProperty(i)) { console.log(i); // выведет 0, 1, 2, "foo" }}
Цикл аналогичен предыдущему, но используетhasOwnProperty()
для проверки того, собственное ли это свойство объекта или унаследованное. Выводятся только собственные свойства. Имена0
,1
,2
иfoo
принадлежат только экземпляру объекта (не унаследованы). МетодыarrCustom
иobjCustom
не выводятся, поскольку ониунаследованы.
for (let i of iterable) { console.log(i); // выведет 3, 5, 7}
Этот цикл обходитiterable
и выводит те значенияитерируемого объекта, которые определены в способе его перебора, т.е. не свойства объекта, а значения массива3
,5
,7
.
Спецификации
Specification |
---|
ECMAScript® 2026 Language Specification # sec-for-in-and-for-of-statements |