闭包与计数器堆叠问题咨询:多timer实例致计数步长异常
问题原因分析与解决方案
嘿,这个问题的核心是变量作用域的问题,咱们一步步拆解来看:
为什么会出现“实例越多,每次递增数值越大”的现象?
你代码里的counter没有用var/let/const声明,这意味着它是一个全局变量——所有通过addTimer创建的定时器,都会共享同一个counter变量。
咱们理一理实际执行流程:
- 第一次调用
addTimer("#timerTag", "red", 1000):把全局counter设为0,启动一个定时器,每秒执行一次timeIt,每次执行都会让counter++。这时候只有一个定时器,所以每秒数值加1,显示正常。 - 第二次调用
addTimer("#tt", "blue", 1000):先把全局counter重置为0,再启动第二个定时器,这个定时器的timeIt同样操作全局的counter。现在每秒有两个定时器同时触发,每个都执行counter++,所以数值每次跳2。 - 第三次调用后,三个定时器每秒各执行一次
counter++,自然每次就加3了。
怎么修复这个问题?
只需要把counter变成addTimer函数的局部变量,让每个addTimer调用都拥有独立的counter,这样每个定时器的timeIt闭包捕获的都是自己专属的变量。修改后的代码如下:
function addTimer(elementID, cssColor, time){ // 用let声明局部变量counter,每个addTimer调用都会创建独立的counter实例 let counter = 0; function timeIt(){ $(elementID).text(counter); $(elementID).css("color", cssColor); counter ++; } setInterval(timeIt, time) } addTimer("#timerTag", "red", 1000) addTimer("#tt", "blue", 1000) addTimer("#ttt", "pink", 1000)
这样每个定时器都会维护自己的独立计数,互相不会干扰,每个实例都会每秒递增1啦~
内容的提问来源于stack exchange,提问作者Munerz




