如何在JavaScript中同时运行多个setTimeout并解决循环变量取值异常问题
问题根因
- 代码中
var声明的变量为函数/全局作用域,全循环共用同一个i和amt实例,循环执行结束后i最终值为10,所有异步触发的checktime引用的都是最终的i值,因此输出的i全为10。 - 不同循环的
amt变量没有独立隔离,多个checktime的计数逻辑会互相冲突,无法实现每个i对应独立计数的需求。
实现方案
核心解决思路是为每次循环创建独立作用域,隔离每个循环的i和amt变量,两种常见实现方式如下:
// 方案1:ES6+ 用let创建块级作用域 for (let i = 0; i < 10; i++) { let amt = 0; function checktime() { console.log(`${amt} / ${i}`); amt++; if (amt <= 5) { setTimeout(checktime, 3000); } } checktime(); } // 方案2:ES5 用IIFE(立即执行函数)创建独立作用域 for (var i = 0; i < 10; i++) { (function(currentI) { var amt = 0; function checktime() { console.log(amt + " / " + currentI); amt++; if (amt <= 5) { setTimeout(checktime, 3000); } } checktime(); })(i); }
方案说明
- 方案1中
let支持块级作用域,每次循环都会生成独立的i和amt实例,每个checktime会绑定当前循环的变量,互不干扰。 - 方案2通过立即执行函数为每次循环创建独立的函数作用域,将当前
i作为参数传入保存,内部维护独立的计数变量,可兼容旧版本JS运行环境。 - 两种方案均可实现需求:首轮立即输出
0/0到0/9的全部内容,之后每3秒各i对应的计数独立自增,直到输出到5/9后停止。
内容的提问来源于stack exchange,提问作者Huddy
相关产品推荐
相关产品推荐

