开源地址https://www.duanshuilu.com/总结前端JavaScript写的for循环和遇到的最近在刷题的时候几个不同的for循环,因为没有深入的了解,做题的时候分不清它们的用法,特别是什么时候用,用起来要注意什么。因此,本文主要对js中的四种for循环进行总结和区分。文末通过一道面试题来加深对不同for循环的理解和使用。遍历数组很常见,这里有一点:Array在Javascript中是一个对象,Array的索引就是属性名。这里输出的索引值,即“0”、“1”、“2”不是Number类型的,而是String类型的,因为它们是作为属性输出的,不是索引。在ECMAScript5(简称ES5)中,有3种for循环,分别是:for,for-in,forEach在2015年6月发布的ECMAScript6(简称ES6)中,新增了一种循环,即:for-接下来说说这四个循环的写法和适用场景。简单的for循环---将代码块循环一定次数来看看常见的写法:constarr=[1,2,3];for(leti=0;i {console.log(data);});//输出如下//1//2//3[![复制代码]forEach方法对数组中包含有效值的每一项执行回调函数,以及那些已被删除的项(使用delete方法等)或从未被赋值的将被跳过(不包括那些值为undefined或null的)。回调函数会依次传入三个参数:数组中当前项的值;数组中当前项的索引;数组对象本身;添加数组中当前项的索引参数。注意回调函数中三个参数的顺序是固定的,不能调整。[![复制代码]constarr=[1,2,3];arr.forEach((data,index,arr)=>{console.log("arr\["+index+"\]="+data);});//输出结果如下//arr[0]=1//arr[1]=2//arr[2]=3[![复制代码]需要注意的是forEach遍历的范围是将在第一次调用回调之前确定。调用forEach后添加到数组的项目将不会被回调访问。如果已经存在的值被更改,则传递给回调的值是forEach遍历到它们时的值。不遍历删除的项目。[![复制代码]constarr=[];arr[0]="a";arr[3]="b";arr[10]="c";arr.name="Helloworld";arr.forEach((data,index,array)=>{console.log(data,index,array);});[![复制代码]运行结果:a0["a",empty×2,"b",empty×6,"c",name:"Helloworld"]b3["a",empty×2,"b",empty×6,"c",name:"Helloworld"]c10["a",empty×2,"b",empty×6,"c",name:"Helloworld"]这里的索引是Number类型的,不会像for-in那样遍历原型链上的属性。因此,在使用forEach的时候,我们不需要特别声明要遍历的索引和元素,因为这些都是作为回调函数的参数。另外,forEach会遍历数组中的所有元素,但是ES5定义了一些其他有用的方法,下面是一些:elements满足回调函数map:处理原数组中的元素再返回reduce:依次处理数组中的元素,将上一次处理的结果作为下一次处理的输入,最终得到FinalResults。for-of---ES6新引入的循环//输出结果如下//a//b//cES6之前的三个for循环有什么缺陷:forEachcannotbreakandreturn;for-in的缺点比较明显,它不仅会遍历数组中的元素,还会遍历自定义属性,甚至连原型链上的属性都会被访问。此外,遍历数组元素的顺序可能是随机的。因此,针对以上缺陷,我们需要对原有的for循环进行改进。但是ES6不会破坏您已经编写的JS代码。目前有数以千计的网站依赖for-in循环,其中一些甚至将其用于数组遍历。通过修复for-in循环来添加数组遍历支持会使这一切更加混乱,因此标准委员会为ES6添加了一个新的循环语法来解决当前的问题,即for-of。那么for-of到底能做什么呢?与forEach相比,可以正确响应break、continue、return。for-of循??环不仅支持数组,还支持大多数类数组对象,例如DOMnodelist对象。for-of循环还支持字符串遍历,将一个字符串当作一系列Unicode字符进行遍历。for-of还支持Map和Set(都是ES6中新增的)对象遍历。总结一下,for-of循环有以下特点:这是遍历数组元素最简洁直接的语法。这种方法避免了for-in循环的所有缺陷。与forEach不同,它可以正确响应break、continue和return语句。它不仅可以遍历数组,还可以遍历类数组对象和其他可迭代对象。但是需要注意的是for-of循环不支持普通对象,但是如果你想遍历一个对象的属性,可以使用for-in循环(这也是它的原生工作)。最后要说的是ES6引入的另一种方法也可以实现遍历数组的值,那就是Iterator。最后一个例子:[![copycode]constarr=['a','b','c'];constiter=arr[Symbol.iterator]();iter.next()//{value:'a',done:false}iter.next()//{value:'b',done:false}iter.next()//{value:'c',done:false}iter.next()//{value:undefined,done:true}[![复制代码]这个内容超出了本文的范围,Iterator还有很多话要说。有兴趣的可以自己去看看,要不等我学了之后再整理。最后贴一下最近一个涉及forEach和for-of去其他大厂的面试题:问题XX:输出如下代码运行结果,why?如果想每1s输出一个结果,应该怎么修改呢?请注意,无法更改平方方法。[![复制代码]1constlist=[1,2,3]2constsquare=num=>{3returnnewPromise((resolve,reject)=>{4setTimeout(()=>{5resolve(num*num)6},1000)7})8}910functiontest(){11list.forEach(asyncx=>{12constres=awaitsquare(x)13console.log(res)14})15}16test()[![复制代码]分析:forEach不能阻塞,默认请求并行发起,所以同时输出1、4、9。方法一:将forEach换成普通的for循环或者for...of...循环forloopasyncfunctiontest(){for(leti=0,len=list.length;i{promise\=promise.then(()=>square(x)).then((res)=>{console.log(res)})})}[![复制代码]还有其他的方法但是比较麻烦,这里就不提了.它的思想主要类似于koa中的compose思想和next思想,即koa1的中间件执行思想。