for...of
语句在TypedArray
,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
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.
语法
for (variable of iterable) { //statements }
-
variable
- 在每次迭代中,将不同属性的值分配给变量。
-
iterable
- 被迭代枚举其属性的对象。
示例
迭代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
对象:下面的例子演示给每一个 article 标签内的 p 标签添加一个 "read
" 类。
//注意:这只能在实现了NodeList.prototype[Symbol.iterator]的平台上运行 let articleParagraphs = document.querySelectorAll("article > p"); for (let paragraph of articleParagraphs) { paragraph.classList.add("read"); }
关闭迭代器
对于for...of
的循环,可以由break
, throw continue
或return
终止。在这些情况下,迭代器关闭。
function* foo(){ yield 1; yield 2; yield 3; }; for (let o of foo()) { console.log(o); break; // closes iterator, triggers return }
迭代生成器
你还可以迭代一个生成器:
function* fibonacci() { // 一个生成器函数 let [prev, curr] = [0, 1]; for (;;) { // while (true) { [prev, curr] = [curr, prev + curr]; yield curr; } } for (let n of fibonacci()) { console.log(n); // 当n大于1000时跳出循环 if (n >= 1000) break; }
不要重用生成器
生成器不应该重用,即使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); }
迭代其他可迭代对象
你还可以迭代显式实现可迭代协议的对象:
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...of
语句遍历可迭代对象定义要迭代的数据。
以下示例显示了与Array
一起使用时,for...of
循环和for...in
循环之间的区别。
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.prototype
。由于继承和原型链,对象iterable
继承属性objCustom
和arrCustom
。
for (let i in iterable) { console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom" }
此循环仅以原始插入顺序记录iterable
对象的array iteration and for...in
中有更多解释。
for (let i in iterable) { if (iterable.hasOwnProperty(i)) { console.log(i); // logs 0, 1, 2, "foo" } }
这个循环类似于第一个,但是它使用hasOwnProperty()
来检查,如果找到的枚举属性是对象自己的(不是继承的)。如果是,该属性被记录。记录的属性是0
, 1
, 2
和foo
,因为它们是自身的属性(不是继承的)。属性arrCustom
和objCustom
不会被记录,因为它们是继承的。
for (let i of iterable) { console.log(i); // logs 3, 5, 7 }
该循环迭代并记录iterable
作为可迭代对象定义的迭代值,这些是数组元素 3
, 5
, 7
,而不是任何对象的属性。
规范
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) for...of statement |
Standard | Initial definition. |
ECMAScript Latest Draft (ECMA-262) for...of statement |
Draft |
浏览器兼容
Desktop | Mobile | Server | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
for...of |
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 38 | 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 Full support 12 | Firefox Full support 57 | IE No support No | Opera Full support 50 | Safari ? | WebView Android Full support 63 | Chrome Android Full support 63 | Firefox Android Full support 57 | Opera Android Full support 46 | Safari iOS ? | Samsung Internet Android Full support 8.0 | nodejs ? |
Closing iterators | Chrome Full support 51 | Edge Full support 14 | 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 51 | 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.