foreach难道真的只是for..of简简单单的语法糖吗?

foreach的云云

问题引入

大佬们先看看两份代码以及执行结果,一份是使用原生for of,另一份是foreach。
这是在写异步操作的时候我遇到的一个问题,开始使用foreach的时候,结果总是不对,我没有给出来的处理代码里对于foreach遍历结果e的处理完全是错乱的,导致达不到预期目的。。。。
后来改成for of之后奇迹般的对了,,,这是个老坑了看提交记录应该是两个星期前的问题。。最近没什么时间研究,今天终于捡起来看看。
出现这种原因,首先我就想要去看foreach封装,我想出现差错的原因一定在于源码中的一些封装问题。

for (let item of array) {//
				console.log("异步开始");
				let res = await this.$service.xxx//这个xxx是指调用的接口服务
				console.log("异步结束" + res);
				//下面是其他一下处理代码就不放上来了
			}

foreach难道真的只是for..of简简单单的语法糖吗?

			this.array.forEach(async (e) => {
				console.log("异步开始");
				let res = await this.$service.xxx;
				console.log("异步结束" + res);
				
			});

foreach难道真的只是for..of简简单单的语法糖吗?
ok不废话了,开始分析。。。

官方解析:forEach的基础用法

foreach难道真的只是for..of简简单单的语法糖吗?
可以看到forEach的两个参数,callbackfun(回调函数)以及thisArg。

callbackfun的三个参数分别是

  1. 数组当前项的值
  2. 数组当前项的索引
  3. 数组本身

举个例子来看一下:

      var arr = [1, 2, 3, 4, 5];
      arr.forEach(function (a, b, c, d) {
        console.log(a);
        console.log(b);
        console.log(c);
      });

运行结果:
foreach难道真的只是for..of简简单单的语法糖吗?
好的了解了回调函数的参数之后,我们来看看thisArg是什么.
foreach难道真的只是for..of简简单单的语法糖吗?
解释一下:如果我们调用forEach的时候提供了thisArg,那么它将作为回调callbackfn的this。如果说没有,那么就会被定义程undefined,此时的this就是全局了window。
依旧举个例子:

var array1 = ["a", "b", "c"];
      var array2 = ["1", "2", "3"];
      array1.forEach(function (value, index, arr) {
        console.log(value, index, arr, this);
      }, array2);

foreach难道真的只是for..of简简单单的语法糖吗?
ok,到这里的话,就已经对于forEach的一些参数认知到了。接下来分析过程

回调分析

依旧是官方这边的过程分析
foreach难道真的只是for..of简简单单的语法糖吗?
注意一个点:回调的执行。

注意回调是不会占用主线程的执行的,假设我们的回调函数是一个计时器,那么这个k值地自增依旧会继续下去,回调并不占用主线程地执行。也就是说,forEach内部实现地就是这么一个回调函数。

ok,讲到这里我们看前面地问题。我们在forEach内部使用了await了。await是什么,异步操作,本质上与回调是差不多地性质,都是在不干扰主线程地情况下运行着程序。那么问题来了。我在这个forEach相当于执行了两次回调函数。

			this.array.forEach(async (e) => {
				console.log("异步开始");
				let res = await this.$service.xxx;
				console.log("异步结束" + res);
				
			});

这样的后果是什么。
我们知道for循环去执行一个遍历操作是飞快地。也就是在程序跑起来的一瞬间,几乎array这个数组内所有的回调函数都跑起来了,他们做的事情都是我现在写的这个await。当await函数结束了之后就会找到this.array.forEach这个线程中,将await异步得到的结果赋值给res重新执行后面的处理操作。

注意,上面这段分析中有两个重点:

  1. 几乎一瞬间所有的回调都跑起来了
  2. await结束,它的结果会自动找到主线程去赋值给res

既然如此,所有的这些回调都是一个函数,对于时间上的结束,他们的前后关系其实差异并不大。既然如此,res那里接受的返回值,就不仅仅是一个await的返回了。

我想这就是我那段代码出错的原因了。

反观for…of 人家就是一次循环一次大括号里的代码,说到底就是一个callbck的问题。

总结

所以说想要满足循环的条件下,又想用await,是不是用for…of会好一点。23333333

啊对于我这种英语废铁来说看那个英文语言规范简直要了我的命。。。创作不易啊,希望可以帮到大家,如果有什么问题,请及时指正!!

上一篇:一个异步请求引起的错误


下一篇:async await 异步 等待 按顺序执行