点击器游戏中JavaScript函数每秒执行次数异常超标问题
问题根源与解决方案
问题原因
你的判断完全正确:每次点击升级按钮时都会调用setInterval(increment1, 1000),这会创建一个新的独立定时器。购买N次升级后,就会有N个定时器同时每秒执行一次increment1函数,每个定时器都会累加一次perSec,最终实际每秒收益是perSec × N,导致收益呈指数级增长。
修复方案
核心思路是只维护一个全局定时器,通过perSec变量动态控制每秒收益,而不是每次买升级都新增定时器。
方案1:页面初始化时启动全局定时器
直接在脚本最外层启动唯一的定时器,无论是否购买升级,定时器都会运行(初始perSec为0时不会产生收益,不影响):
// 全局仅启动一次定时器,负责每秒更新收益 setInterval(increment1, 1000); upgradePerSec1.onclick = function() { if (presents >= cost1) { presents -= cost1; upgrade1Amount += 1; totalPresentsSpent += cost1; cost1 = Math.ceil(cost1Base *= 1.03 ** upgrade1Amount); perSec += 0.1; displayScore.innerHTML = format(presents) + " Presents delivered."; cost1Disp.innerHTML = "<hr>Cost: " + format(cost1); title.innerHTML = format(presents) + " Presents"; perSecDisp.innerHTML = formatPerSec(perSec) + " presents /s"; totalPresentsSpentDisp.innerHTML = format(totalPresentsSpent) + " Total presents spent"; // 移除此处的setInterval调用 } else { alert("You don't have enough presents! Still need: " + format(cost1 - presents)); } } function increment1() { presents += perSec; totalPresents += perSec; displayScore.innerHTML = format(presents) + " Presents delivered."; totalPresentsDisp.innerHTML = format(totalPresents) + " Total presents delivered"; title.innerHTML = format(presents) + " Presents"; }
方案2:首次购买时启动定时器
如果希望避免无收益时定时器空跑,可以添加一个变量判断,仅在第一次购买升级时启动定时器:
let incomeInterval = null; // 存储定时器ID,用于后续控制 upgradePerSec1.onclick = function() { if (presents >= cost1) { presents -= cost1; upgrade1Amount += 1; totalPresentsSpent += cost1; cost1 = Math.ceil(cost1Base *= 1.03 ** upgrade1Amount); perSec += 0.1; displayScore.innerHTML = format(presents) + " Presents delivered."; cost1Disp.innerHTML = "<hr>Cost: " + format(cost1); title.innerHTML = format(presents) + " Presents"; perSecDisp.innerHTML = formatPerSec(perSec) + " presents /s"; totalPresentsSpentDisp.innerHTML = format(totalPresentsSpent) + " Total presents spent"; // 仅当定时器未启动时创建 if (!incomeInterval) { incomeInterval = setInterval(increment1, 1000); } } else { alert("You don't have enough presents! Still need: " + format(cost1 - presents)); } } function increment1() { presents += perSec; totalPresents += perSec; displayScore.innerHTML = format(presents) + " Presents delivered."; totalPresentsDisp.innerHTML = format(totalPresents) + " Total presents delivered"; title.innerHTML = format(presents) + " Presents"; }
额外提示
如果后续需要添加暂停/加速功能,可以通过clearInterval(incomeInterval)停止定时器,再重新调用setInterval创建新的定时器来实现。
内容的提问来源于stack exchange,提问作者bstplyr2401
相关产品推荐
相关产品推荐

