JavaScript setInterval写在函数内部的实现与最佳实践问题咨询
问题1:setInterval放入函数内部的实现方案与最佳实践
错误原因
你第三段代码运行失败的核心原因是没有手动触发第一次logger函数执行:setInterval定义在logger内部,只有logger被调用时才会执行注册定时器的逻辑,你只定义了函数没有调用的话,定时器永远不会被注册,自然没有输出。
可行实现
如果要实现逻辑闭环,只需要在定义函数后手动调用一次即可,不过这里有个严重的隐患:
function logger() { console.log("log some stuff..."); setInterval(logger, 3000); } logger(); // 手动触发第一次执行
上述代码运行后,每3秒就会新增一个定时器,最终会有N个定时器同时执行,控制台打印频率会越来越高,最终导致性能问题。
如果要避免重复注册定时器的问题,更推荐用setTimeout替代setInterval写在函数内部:
function logger() { console.log("log some stuff..."); setTimeout(logger, 3000); // 每次执行完只注册下一次的执行,不会重复生成定时器 } logger();
最佳实践判断
- 使用
setTimeout递归调度的写法属于推荐实践:可以规避原生setInterval的执行堆积问题——如果定时器回调执行时长超过设置的间隔,setInterval会跳过部分执行或者出现回调堆叠,而setTimeout的写法能保证两次执行的间隔始终符合预期。 - 使用
setInterval写在函数内部的写法属于不推荐实践:极易出现重复注册定时器的问题,引发内存泄漏和执行逻辑异常。
问题2:时间不更新的原因
这个问题确实和作用域相关,核心是变量赋值时机错误:
你把var now = new Date()定义在了setInterval回调的外部,只会在logger函数被调用时执行一次赋值,后续setInterval的所有回调访问的都是同一个首次创建的Date对象,自然时间不会变化。
修正方案是把时间获取逻辑放到回调内部,每次执行都重新获取当前时间:
function logger(output, interval) { setInterval(function() { var now = new Date(); // 每次执行回调都重新获取当前时间 console.log(output, now.toLocaleString()); }, interval) } logger("Foo ", 3000);
内容的提问来源于stack exchange,提问作者equanimity
相关产品推荐
相关产品推荐

