Доброволците ни все още не са превели статията на Български. Присъединете се и помогнете да свършим тая работа!
Можете да прочетете статията и на English (US).
The for...of
statement creates a loop iterating over iterable objects, including: built-in String
, Array
, Array
-like objects (e.g., arguments
or NodeList
), TypedArray
, Map
, Set
, and user-defined iterables. It invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
Syntax
for (variable of iterable) { statement }
variable
- On each iteration a value of a different property is assigned to variable.
iterable
- Object whose iterable properties are iterated.
Examples
Iterating over an Array
let iterable = [10, 20, 30]; for (let value of iterable) { value += 1; console.log(value); } // 11 // 21 // 31
You can use const
instead of let
too, if you don't reassign the variable inside the block.
let iterable = [10, 20, 30]; for (const value of iterable) { console.log(value); } // 10 // 20 // 30
Iterating over a String
let iterable = 'boo'; for (let value of iterable) { console.log(value); } // "b" // "o" // "o"
Iterating over a TypedArray
let iterable = new Uint8Array([0x00, 0xff]); for (let value of iterable) { console.log(value); } // 0 // 255
Iterating over a 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
Iterating over a Set
let iterable = new Set([1, 1, 2, 2, 3, 3]); for (let value of iterable) { console.log(value); } // 1 // 2 // 3
Iterating over the arguments object
You can iterate over the arguments
object to examine all of the parameters passed into a JavaScript function:
(function() { for (let argument of arguments) { console.log(argument); } })(1, 2, 3); // 1 // 2 // 3
Iterating over a DOM collection
Iterating over DOM collections like NodeList
: the following example adds a read
class to paragraphs that are direct descendants of an article:
// Note: This will only work in platforms that have // implemented NodeList.prototype[Symbol.iterator] let articleParagraphs = document.querySelectorAll('article > p'); for (let paragraph of articleParagraphs) { paragraph.classList.add('read'); }
Closing iterators
In for...of
loops, abrupt iteration termination can be caused by break
, continue
, throw
or return
. In these cases, the iterator is closed.
function* foo(){ yield 1; yield 2; yield 3; }; for (let o of foo()) { console.log(o); break; // closes iterator, triggers return }
Iterating over generators
You can also iterate over generators, i.e. functions generating an iterable object:
function* fibonacci() { // a generator function let [prev, curr] = [0, 1]; while (true) { [prev, curr] = [curr, prev + curr]; yield curr; } } for (let n of fibonacci()) { console.log(n); // truncate the sequence at 1000 if (n >= 1000) { break; } }
Do not reuse generators
Generators should not be re-used, even if the for...of
loop is terminated early, for example via the break
keyword. Upon exiting a loop, the generator is closed and trying to iterate over it again does not yield any further results.
var gen = (function *(){ yield 1; yield 2; yield 3; })(); for (let o of gen) { console.log(o); break; // Closes iterator } // The generator should not be re-used, the following does not make sense! for (let o of gen) { console.log(o); // Never called. }
Iterating over other iterable objects
You can also iterate over an object that explicitly implements the iterable protocol:
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
Difference between for...of
and for...in
Both for...in
and for...of
statements iterate over something. The main difference between them is in what they iterate over.
The for...in
statement iterates over the enumerable properties of an object, in an arbitrary order.
The for...of
statement iterates over values that the iterable object defines to be iterated over.
The following example shows the difference between a for...of
loop and a for...in
loop when used with an 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 }
Let us look into the above code step by step.
Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; let iterable = [3, 5, 7]; iterable.foo = 'hello';
Every object will inherit the objCustom
property and every object that is an Array
will inherit the arrCustom
property since these properties have been added to Object.prototype
and Array.prototype
, respectively. The object iterable
inherits the properties objCustom
and arrCustom
because of inheritance and the prototype chain.
for (let i in iterable) { console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom" }
This loop logs only enumerable properties of the iterable
object, in original insertion order. It doesn't log array elements 3
, 5
, 7
or hello
because those are not enumerable properties, in fact they are not properties at all, they are values. It logs array indexes as well as arrCustom
and objCustom
, which are. If you're not sure why these properties are iterated over, there's a more thorough explanation of how array iteration and for...in
work.
for (let i in iterable) { if (iterable.hasOwnProperty(i)) { console.log(i); // logs 0, 1, 2, "foo" } }
This loop is similar to the first one, but it uses hasOwnProperty()
to check if the found enumerable property is the object's own, i.e. not inherited. If it is, the property is logged. Properties 0
, 1
, 2
and foo
are logged because they are own properties (not inherited). Properties arrCustom
and objCustom
are not logged because they are inherited.
for (let i of iterable) { console.log(i); // logs 3, 5, 7 }
This loop iterates and logs values that iterable
, as an iterable object, defines to be iterated over. The object's elements 3
, 5
, 7
are shown, but none of the object's properties.
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'for...of statement' in that specification. |
Standard | Initial definition. |
ECMAScript Latest Draft (ECMA-262) The definition of 'for...of statement' in that specification. |
Draft |
Browser compatibility
Desktop | Mobile | Server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Basic support | Chrome Full support 38 | Edge Full support 12 | Firefox
Full support
13
| IE No support No | Opera Full support 25 | Safari Full support 8 | WebView Android Full support 38 | Chrome Android Full support Yes | Edge Mobile Full support 12 | Firefox Android
Full support
14
| Opera Android Full support 25 | Safari iOS Full support 8 | Samsung Internet Android Full support Yes | nodejs Full support Yes |
async iterators | Chrome Full support 63 | Edge ? | Firefox Full support 57 | IE No support No | Opera Full support 50 | Safari ? | WebView Android Full support 63 | Chrome Android Full support 63 | Edge Mobile ? | Firefox Android Full support 57 | Opera Android Full support 50 | Safari iOS ? | Samsung Internet Android ? | nodejs ? |
Closing iterators | Chrome Full support 51 | Edge Full support Yes | Firefox Full support 53 | IE No support No | Opera Full support Yes | Safari Full support Yes | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile Full support Yes | Firefox Android Full support 53 | Opera Android Full support Yes | Safari iOS Full support Yes | Samsung Internet Android Full support Yes | nodejs Full support Yes |
Legend
- Full support
- Full support
- No support
- No support
- Compatibility unknown
- Compatibility unknown
- See implementation notes.
- See implementation notes.