为什么setInterval中已定义的var变量仍重复打印?不清除定时器如何解决?
问题解答
现象原因
核心是var声明的函数作用域特性+变量提升机制导致:
- 直接在全局控制台执行代码时,
var TEST声明挂载在全局作用域,首次执行后全局就存在已赋值的TEST变量,再次执行时typeof TEST返回boolean,判断不成立,符合预期。 - 逻辑放入
setInterval回调后,var TEST是声明在回调函数的独立作用域内:- 每次回调函数执行前,JS会预先扫描当前函数内所有
var声明,将对应变量提升到当前函数作用域顶部,初始值为undefined - 执行
typeof TEST === "undefined"判断时,优先访问当前函数作用域内刚提升、未赋值的TEST,结果永远为真 - 函数内的
TEST变量会遮蔽全局作用域的同名变量,全局是否存在TEST完全不影响当前函数内的判断逻辑,因此每次回调都会进入分支打印日志。
- 每次回调函数执行前,JS会预先扫描当前函数内所有
解决方法(不清除定时器的前提下)
核心逻辑是避免在回调函数内部重新声明TEST变量,直接使用外层/全局作用域的变量做判断:
- 方案1:直接判断全局对象属性,避免函数作用域变量遮蔽
setInterval(function(){ if(typeof window.TEST === "undefined") { window.TEST = true; console.log(TEST); } }, 1000);
- 方案2:将变量声明移到回调函数外层,使用外层作用域存储状态
var TEST; setInterval(function(){ if(typeof TEST === "undefined") { TEST = true; console.log(TEST); } }, 1000);
- 方案3:使用现代JS的块级作用域关键字
let替代var,逻辑同方案2,避免意外的变量提升问题
let TEST; setInterval(function(){ if(typeof TEST === "undefined") { TEST = true; console.log(TEST); } }, 1000);
内容的提问来源于stack exchange,提问作者MShack
相关产品推荐
相关产品推荐

