关键在搞清变量生命周期和作用域边界——异步回调执行时,变量早已不是你“以为”的那个值;用 let 替代 var 可解决循环变量捕获问题,因 let 创建块级作用域,每次迭代生成独立绑定,而 var 是函数作用域、共用同一变量实例。

关键在搞清变量生命周期和作用域边界——异步回调执行时,变量早已不是你“以为”的那个值。
用 let 替代 var 声明循环变量
var 声明的变量具有函数作用域,整个循环共用一个变量实例;而 let 创建块级作用域,每次迭代都生成独立绑定。
- 错误写法(var):所有回调读到的都是循环结束后的 final 值
- 正确写法(let):每个 setTimeout / AJAX 回调捕获的是当前轮次的变量值
- 示例中 singleAudio 改为 let singleAudio = 0,就能让
console.log(singleAudio)输出 0、1、2 而非全为 3
避免在回调中直接引用外部循环变量
即使用了 let,若在回调里访问的是被后续迭代修改的对象属性(比如 selectedAudios[i] 的某个字段),仍可能出错。
- 推荐在循环体内提前解构或拷贝关键值:如
const currentName = selectedAudios[i].name - 对对象/数组等引用类型,必要时用
{...obj}或Array.from(arr)浅拷贝 - 不要依赖“循环还没结束,对象肯定没变”这种假设——异步回调不保证执行时机
函数参数比闭包更清晰可靠
当无法使用 let(如兼容老环境),用立即执行函数传参比手动写闭包更直观、不易出错。
- 旧方案:
(function(index) { ... })(i) - 现代替代:
for (let i = 0; i ,把 i 当参数传进 async 函数内部 - 参数传递天然隔离作用域,比闭包更易理解和调试
警惕隐式提升与未声明变量
async 函数内若漏写 let/const,变量会自动挂到全局,多个并发请求可能互相覆盖。
- 例如:
result = await fetch(...)(没声明)→ 全局污染 - 应始终显式声明:
const result = await fetch(...) - 开启严格模式(
"use strict")可让这类错误直接抛异常,避免静默失败
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











