使用 setTimeout 解决 JavaScript for 循环打印不连续值问题

阅读时长 3 分钟读完

JavaScript 是一门单线程语言,且其执行机制是基于事件循环队列的。当代码中遇到异步事件时,实际上是将该事件加入到事件循环队列中,等待执行。

在前端开发中,经常会使用 for 循环来处理数据,如下面这个例子:

预期输出结果为:

但实际上的输出结果为:

这是因为 setTimeout 是一个异步事件,它会被添加到事件循环队列中,等待 JavaScript 引擎空闲时再执行。而在 setTimeout 回调函数中,我们访问的是 for 循环中的变量 i,而这个变量在 setTimeout 执行时已经等于了 5,因此输出结果全部为 5。

解决方案

要解决这个问题,我们需要使用 JavaScript 的闭包特性。具体地说,对于每个循环中的 setTimeout,我们需要创建一个新的作用域,使得回调函数能够访问到当前循环的索引值 i 的副本,而不是访问循环结束后的 i 值。可以使用 IIFE(立即执行函数表达式)来实现这一点,如下所示:

输出结果为:

这里通过立即执行函数表达式(IIFE)创建了一个新的作用域,并将当前循环的索引值 i 传递给该函数的参数 j,使得回调函数能够访问到 j 的副本。

除了 IIFE,我们还可以使用 ES6 中的 let 关键字,它会创建块级作用域,并且在每次循环迭代时都会创建一个新的变量 j。如下所示:

输出结果同样为:

总结

JavaScript 中的事件循环机制是理解前端异步编程的关键之一。当我们遇到类似于 setTimeout 在循环中的问题时,需要使用闭包或者块级作用域来解决。以上两种方法都可以创建一个新的作用域,使得回调函数能够访问到当前循环的索引值的副本,从而解决了循环中打印不连续值的问题。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/9152

纠错
反馈