用 let 声明循环变量可解决 for 循环中异步操作输出最后一个索引的问题,因其块级作用域使每次迭代的 i 独立;es5 用 iife、数组场景用 foreach、遍历类数组可用 for...of + entries()。

在 JavaScript 中,用 for 循环配合异步操作(比如 setTimeout、事件监听、fetch)时,常会遇到“所有回调都输出最后一个索引”的问题。根本原因是循环变量(如 i)是共享的,而回调执行时循环早已结束,i 已变成最终值。闭包能保存每次迭代时的值,关键在于让每个回调“捕获”当次的索引。
用立即执行函数(IIFE)包裹循环体
这是 ES5 最经典解法:把当前的 i 作为参数传入一个立即执行函数,在其作用域内形成闭包。
for (var i = 0; i <p>说明:</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2847" title="OpenJDK 24"><img src="https://img.php.cn/upload/manual/001/431/639/6ad0919a12f37751.png" alt="OpenJDK 24" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2847" title="OpenJDK 24" class="overflowclass">OpenJDK 24</a> <p class="overflowclass"></p> </div> <a rel="nofollow" href="/xiazai/gongju/2847" title="OpenJDK 24" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
-
var声明的i是函数作用域,整个循环共用一个i; - IIFE 每次调用都创建新作用域,
index是形参,接收当次的i值,被内部函数闭包引用; - 注意括号位置:
(function(){...})(i)或(function(i){...})(i)都可,关键是立即执行并传参。
用 let 声明循环变量(推荐,ES6+)
let 具有块级作用域,每次循环都会为 i 创建一个独立绑定,无需手动闭包。
for (let i = 0; i {
console.log(i); // 输出 0, 1, 2
}, 100);
}
说明:
- 每次迭代的
i是不同的绑定,箭头函数或普通函数都能正确访问它; - 这是最简洁、可读性最强的方式,现代项目应优先使用;
- 注意不能用
var+let混用——for (var i...)仍会出错,必须写成for (let i...)。
用 forEach 替代 for 循环
Array.prototype.forEach 的回调函数天然具有闭包特性,每个元素的索引和值都是独立参数。
[0, 1, 2].forEach(function(item, index) {
setTimeout(() => {
console.log(index); // 输出 0, 1, 2
}, 100);
});
说明:
- 适用于已知数组的情况(如
domList.forEach(...)); - 回调的
index参数每次都是新值,自动形成闭包; - 如果原始数据不是数组,可用
Array.from({ length: n })或[...Array(n).keys()]构造。
用 for...of 配合解构或辅助变量
若需遍历类数组或带索引的结构,可结合 entries() 方法:
for (const [index, item] of [0, 1, 2].entries()) {
setTimeout(() => {
console.log(index); // 输出 0, 1, 2
}, 100);
}
说明:
-
entries()返回键值对迭代器,for...of每次解构出独立的index和item; - 本质仍是块级绑定,每个循环体都有自己的
index变量; - 比传统
for更语义化,适合遍历 Map、Set 或数组。
核心逻辑就一条:确保回调函数引用的变量,在定义时就绑定了当次迭代的值。用 let 是最直接的方式;兼容老环境时用 IIFE;已有数组优先选 forEach 或 for...of。不复杂但容易忽略细节。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










