关于JS的for循环包裹异步函数的问题

今天一个做后端的同事问了我一个JS的问题:

有个循环,循环一个异步回调,为啥回调引用的循环值都是最后一步循环的循环值?然后,又有些时候无论什么循环值都得不到?

好吧,JavaScript跟PHP的循环有时候确实不一样,JavaScript的函数有同步函数跟异步函数的区分,PHP里面没这种概念,拿PHP的常识来理解JavaScript有时候行不通。关于JS异步机制的研究,看我另一篇JS异步执行机制理解。

我想了想,他说的“什么循环值也得不到的”,应该是下面这个情况:


结果是:

5
undefined
5
undefined
5
undefined
5
undefined
5
undefined

for循环有一个特点,就是“i判断失败一次才停止”。所以,i在不断的自加1的时候,直到i等于5,i才失败,这时候循环体不再执行,会跳出,所以i等于5没错。那么为什么5次循环的i都等于5?原因就是setTimeout()的回调,也就是console.log(i);console.log(arr[i]);被压到任务队列的最后,for循环是同步任务,所以先执行,等于是空跑了5次循环。于是,i都等于5之后,console.log(i);console.log(arr[i]);刚开始第一次执行,当然输出全是5。

然后,同事说,有时候JS的for循环,永远只得到最后一个循环值,那其实他用的是for...in...循环。具体不多解释了。

我既然听了他的问题,就要给他解决方案。

我先建议他用自执行函数传参,这样自执行函数内部形成了局部作用域,不受外部变量变化的影响。范例代码是:


得到:

关于JS的for循环包裹异步函数的问题_第1张图片
Paste_Image.png

不但解决了undefined的问题,而且解决了异步函数传参的问题。

然后我把范例代码给了他。然而,他的JS代码写的太乱,拿这个例子改居然改不对。于是我又给了一个jQuery方案给他:


用jQuery的$.each(),自带回调函数,形成了函数作用域,这娃最终解决了问题。

你可能感兴趣的:(关于JS的for循环包裹异步函数的问题)