JavaScript setInterval重复执行 addFarm计数增量异常排查
问题根因
你遇到的每秒双倍增量问题是三个代码缺陷共同导致的:
- 没有提前初始化
addFarm1、addFarm2等状态变量,标志位判断逻辑可能意外触发,导致addFarm被多次调用 - 每次调用
addFarm都会新建一个setInterval定时器,从未清除过旧定时器,定时器会永久叠加运行 - 所有计数变量(
farmCount/farmIncrement/bananaCount)都没有用let/const声明,默认成为全局变量,所有定时器回调都会读取同一个全局farmIncrement值。当你第二次调用addFarm把farmIncrement改为15后,之前创建的旧定时器也会按15计算增量,两个定时器同时运行就会每秒增加30。
修复方案
1. 提前初始化所有状态变量
在代码最顶部统一声明所有用到的变量,避免隐式全局变量和未定义判断错误,同时新增一个变量存储农场定时器ID,方便后续清理:
// 初始化所有全局状态 let bananaCount = 0; let farmCount = 0; let farmIncrement = 0; let addFarm1 = false; let addFarm2 = false; let farmTimer = null; // 存储农场定时器ID
2. 修改addFarm逻辑,避免重复创建定时器
每次更新农场数量、计算新增量后,先清除之前的旧定时器,再创建新的定时器,保证同一时间只有一个农场产出定时器在运行,同时删掉没用的farmAdd = 0赋值(参数是函数内局部变量,赋值无意义):
function addFarm(farmAdd) { farmCount = farmCount + farmAdd; farmIncrement = farmCount * 5; farmCountText.textContent = farmCount + ' (+' + farmIncrement + ')'; // 清除已存在的旧定时器,防止叠加 if (farmTimer) { clearInterval(farmTimer); } // 创建新的产出定时器 farmTimer = setInterval(function() { bananaCount += farmIncrement; bananaCountText.textContent = bananaCount; console.log('当前农场每秒产出:', farmIncrement); }, 1000); }
3. (可选优化)把阈值判断改为互斥逻辑
虽然现有标志位逻辑在变量初始化正常的情况下不会重复触发,但把连续的if改为else if可以避免不必要的判断,也能减少逻辑意外:
function bananaClick() { bananaCount += 1; if (bananaCount > 15000) { bananaClicked.textContent = 'Mario Banana (+23)'; banana.src = 'images/banana7.png'; countByTwo(4); if (!addFarm2) { addFarm(2); addFarm2 = true; } } else if (bananaCount > 10000) { bananaClicked.textContent = 'Golden Banana Bunch (+15)'; banana.src = 'images/banana6.png'; countByTwo(3); if (!addFarm1) { addFarm(1); addFarm1 = true; } } bananaCountText.textContent = bananaCount; }
验证逻辑
修改后触发逻辑如下:
- 香蕉数首次超过10000时,调用1次
addFarm(1),清除空定时器后创建新定时器,每秒产出5 - 香蕉数首次超过15000时,调用1次
addFarm(2),先清除之前每秒产5的旧定时器,再创建新定时器,此时总农场数为3,每秒产出15,只有一个定时器运行,增量符合预期。
内容的提问来源于stack exchange,提问作者kvnza
相关产品推荐
相关产品推荐

