日常工作中经常会用到前两个循环 对于for await of 在实际工作中还是比较少用到的 今天总结一下这三种遍历方式有什么区别?
for in
for...in 语句迭代一个对象的所有可枚举字符串属性(除 Symbol 以外),包括继承的可枚举属性。
for in 循环主要用于遍历对象,同时可以遍历对象上的原型属性
const demo = (object) => {
for (const key in object) {
if (Object.prototype.hasOwnProperty.call(object, key)) {
const element = object[key];
console.log(element);
}
}
};
demo({
a: "1",
b: "2",
c: "3",
});
如果只需要遍历对象上的属性 可以使用Object.prototype.hasOwnProperty.call(object, key)判断是否是原型上的属性,目前推荐的方式是使用Object.hasOwn(object, key),语义化更明显。
或者迭代对象本身自己有的属性使用
Object.keys()
或者
Object.getOwnPropertyNames()
for of
for...of 循环主要用于遍历数组 同时也可以遍历可迭代属性例如Map Set NodeList Array,String,TypedArray等
遍历普通数组
const demo = (object) => {
for (const element of object) {
console.log(element);
}
};
demo([
1,2,3
])
输出 1 2 3
遍历 String 字符串
const demo = (object) => {
for (const element of object) {
console.log(element);
}
};
demo('abcdefg')
输出: a b c d e f g
也可以遍历对象 使用Object.keys() 方法 然后再取值
一般推荐使用 for in 来遍历对象
使用for of 遍历Map对象时还可以提前解构
const all = (object)=>{
for (const [key,value] of object) {
console.log(key,value);
}
}
const iterable = new Map([
["a", 1],
["b", 2],
["c", 3],
]);
all(iterable)
遍历对象同时取值
const demo = (object) => {
for (const element of Object.keys(object)) {
console.log(element,object[element]);
}
};
// demo('abcdefg')
demo({
a: "1",
b: "2",
c: "3",
});
遍历Map对象 遍历Set对象同理
const demo = (object) => {
for (const element of object) {
console.log(element);
}
};
const iterable = new Map([
["a", 1],
["b", 2],
["c", 3],
]);
// demo('abcdefg')
demo(iterable)
提前退出
使用break 可以提前退出
异步迭代 可用于串行执行异步任务
const promise = [Promise.resolve(1),Promise.resolve(2),Promise.resolve(3)]
const all = async (object)=>{
for (const element of object) {
const data = await element
console.log(data);
}
}
all(promise)
for await of
可用于迭代异步任务
for await...of 语句创建一个循环,该循环遍历异步可迭代对象以及同步可迭代对象。该语句只能在可以使用 await 的上下文中使用,包括异步函数体内以及模块中。
const promise = [Promise.resolve(1),Promise.resolve(2),Promise.resolve(3)]
const allawaitof = async (object)=>{
for await (const element of object) {
console.log(element);
}
}
// all(promise)
allawaitof(promise)
上述将await 写在外层 简化了for of循环迭代的过程 循环内部可以直接拿到await后的值。
同时for await of 也可以用于遍历实现了迭代器的数据结构,可用于迭代异步生成器或者实现了迭代器的异步可迭代对象。
迭代实现了迭代器的异步可迭代对象
const LIMIT = 3;
const asyncIterable = {
[Symbol.asyncIterator]() {
let i = 0;
return {
next() {
const done = i === LIMIT;
const value = done ? undefined : i++;
return Promise.resolve({ value, done });
},
return() {
// 如果消费者在循环中提前调用“break”或“return”,则会运行到这里。
return { done: true };
},
};
},
};
(async () => {
for await (const num of asyncIterable) {
console.log(num);
}
})();
迭代异步生成器
async function* asyncGenerator() {
let i = 0;
while (i < 3) {
yield i++;
}
}
(async () => {
for await (const num of asyncGenerator()) {
console.log(num);
}
})();
// 0
// 1
// 2
也可以用来迭代同步可迭代对象和生成器。
应用场景
- 异步读取文件可读流
- 处理fetch axios等网络请求 分块传输网络请求流信息
- 接收websoket 消息 并循环处理消息事件流