如何更新变量使其可以在其他作用域中正常使用
问题根源说明
你遇到的现象并非作用域问题:全局声明的let second = 20可以在定时器回调中正常修改,全局环境下也能访问到修改后的值。核心问题是代码执行顺序:
外层的if (second > 0)判断是脚本加载后同步执行的,此时定时器回调还没触发过,second仍然是初始值20,且这个判断只会执行一次,后续second递减到0时也不会重新触发判断、禁用已绑定的点击逻辑。
解决方案
推荐两种实现方式,按需选择:
方案1:点击时判断投票状态(改动最小)
直接移除外层的if (second > 0)判断,把有效性校验放到点击事件回调内部,每次点击时先检查当前second值,投票已结束就直接终止逻辑执行:
votingEnd = document.querySelector(".imposters__voting"); imposters = document.querySelectorAll(".imposter"); let second = 20; window.addEventListener("load", function () { let myinterval; myinterval = setInterval(function () { second--; if (second < 11) { votingEnd.style.color = "red"; } votingEnd.innerHTML = `Voting ends in: ${second}s`; if (second == 0) { clearInterval(myinterval); votingEnd.innerHTML = `Voting has ended`; } }, 1000); }); // 直接绑定点击事件,不在外层做一次性判断 for (let i = 0; i < imposters.length; i++) { imposters[i].addEventListener("click", function () { // 每次点击都判断投票是否结束,结束就直接返回不执行后续逻辑 if (second <= 0) return; let count = 0; while (count < imposters.length) { imposters[count++].classList.remove("voted"); } this.classList.add("voted"); }); }
方案2:投票结束后直接移除所有点击监听
如果需要彻底禁用事件、避免每次点击都做判断,可以把点击监听函数抽成公共变量,等倒计时归0时遍历移除所有元素的点击监听:
votingEnd = document.querySelector(".imposters__voting"); imposters = document.querySelectorAll(".imposter"); let second = 20; // 抽离点击监听函数,方便后续移除 function handleImposterClick() { let count = 0; while (count < imposters.length) { imposters[count++].classList.remove("voted"); } this.classList.add("voted"); } window.addEventListener("load", function () { let myinterval; myinterval = setInterval(function () { second--; if (second < 11) { votingEnd.style.color = "red"; } votingEnd.innerHTML = `Voting ends in: ${second}s`; if (second == 0) { clearInterval(myinterval); votingEnd.innerHTML = `Voting has ended`; // 投票结束后遍历移除所有点击监听 for (let i = 0; i < imposters.length; i++) { imposters[i].removeEventListener("click", handleImposterClick); } } }, 1000); }); // 页面初始化时直接绑定点击事件 for (let i = 0; i < imposters.length; i++) { imposters[i].addEventListener("click", handleImposterClick); }
内容的提问来源于stack exchange,提问作者Tibo Mertens
相关产品推荐
相关产品推荐

