You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么代码中使用IIFE会导致setTimeout的运行结果产生巨大差异?

问题原理说明

核心差异点

setTimeout的第一个参数要求传入待延迟执行的函数引用,而IIFE(立即执行函数表达式)的本质是「定义即立即执行的函数」,这是两者出现运行差异的根本原因。


正常版本的执行逻辑

你第一个版本的代码,给setTimeout传入的是匿名函数的引用:

let count = 0

function timerFunction(miliseconds) {
  setTimeout(function() {
    console.log('This is iteration number: ' + ++count + ' and it took this many miliseconds to do the iteration:' + miliseconds)
    timerFunction(miliseconds)
  }, miliseconds)
}

timerFunction(2000)

执行流程完全符合预期:

  • 调用timerFunction时,仅把匿名函数本身传给setTimeout注册,没有立刻执行内部逻辑
  • 等待指定毫秒数后,才会触发执行函数内的打印、递归调用逻辑
  • 每次递归都有对应延迟,不会出现无限同步递归的问题

IIFE版本的执行逻辑

第二个版本中,你传给setTimeout的是IIFE的执行结果,而非待延迟的函数:

let count = 0

function timerFunction(miliseconds) {
  setTimeout((function() {
    console.log('This is iteration number: ' + ++count + ' and it took this many miliseconds to do the iteration:' + miliseconds)
    timerFunction(miliseconds)
  })(), miliseconds)
}

timerFunction(2000)

运行时会进入完全错误的执行流程:

  • 调用timerFunction时,JS引擎会先执行作为参数的IIFE,立刻运行内部的打印、递归调用timerFunction逻辑,根本不会等待超时
  • 该IIFE没有返回值,相当于给setTimeout传了undefined,你设置的超时参数完全无效
  • 整个过程没有任何等待,直接进入无限同步递归,调用栈被快速占满,最终抛出栈溢出错误

拓展:如果需要用IIFE的正确写法

如果确实需要用到IIFE做一些初始化逻辑,可以让IIFE返回待延迟执行的函数引用即可:

setTimeout((function() {
  // 此处可写需要立刻执行的初始化逻辑
  return function() {
    // 要延迟执行的逻辑放在返回的函数内
    console.log('This is iteration number: ' + ++count + ' and it took this many miliseconds to do the iteration:' + miliseconds)
    timerFunction(miliseconds)
  }
})(), miliseconds)

内容的提问来源于stack exchange,提问作者Jim Jay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 19:48:04