for...of - JavaScript 编辑
for...of
语句在可迭代对象(包括 Array
,Map
,Set
,String
,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
的每个对象将继承arrCustom
属性,因为将这些属性添加到Object.prototype
和Array.prototype
。由于继承和原型链,对象iterable
继承属性objCustom
和arrCustom
。
for (let i in iterable) {
console.log(i); // logs 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); // 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 (ECMA-262) for...of statement | Living Standard |
浏览器兼容
BCD tables only load in the browser
The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.相关链接
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论