异步回调中变量值“变掉”的根本原因是访问当前值而非注册时的值,需用闭包锁定瞬时值;let循环可避免var共享问题;事件监听需保存this或用箭头函数绑定。

异步回调中变量值“变掉了”,根本原因是函数执行时访问的是变量的**当前值**,而不是定义或注册时的值。要让回调拿到注册那一刻的变量状态,核心办法是利用闭包把当时的值“锁住”。
用闭包捕获瞬时值
把外层变量作为参数传给一个立即执行的函数,由它返回真正要执行的回调函数。这样参数值就被封闭在内层函数的作用域里,不受后续修改影响。
- 写法示例:
let x = "原始值";
setTimeout((function(val) { return function() { console.log(val); }; })(x), 1000);
x = "新值"; // 不影响输出 - 关键点:外层函数调用时就接收了 x 的快照,内层函数通过词法作用域读取这个固定值
用箭头函数配合参数传递
如果回调逻辑简单,可以直接在 setTimeout 第一个参数里写箭头函数,并把变量作为参数传进去。
- 写法示例:
let count = 0;
for (let i = 0; i setTimeout(() => console.log(i), 100);
count++;
} - 注意:这里依赖的是 let 声明的块级作用域,每次循环都生成独立的 i,不是靠闭包“手动锁值”
避免 var 声明引发的共享问题
var 声明的变量没有块级作用域,在 for 循环中所有 setTimeout 共享同一个 i 变量,导致最后都输出循环结束后的值(如 5)。
立即学习“Java免费学习笔记(深入)”;
- 错误写法:
for (var i = 0; i setTimeout(() => console.log(i), 100);
} → 全部输出 5 - 修复方式:改用 let,或用闭包包裹 var 的 i(如 IIFE)
事件监听器中保存 this 或上下文
绑定事件时,回调里的 this 通常指向触发元素,而不是外层对象。需要提前把 this 存下来再传入。
- 常见做法:
const self = this;
btn.addEventListener('click', function() { self.handleClick(); }); - 更简洁方式:用箭头函数(自动继承外层 this),或用
bind(this)


















