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

循环中IIFE函数与setTimeout()的运行逻辑解析请求

解析循环中setTimeout的两种写法:标准写法 vs IIFE写法

Let's walk through exactly what's happening with both code snippets when you run them in Node.js—this all boils down to how JavaScript handles variable scope and closures with asynchronous functions like setTimeout.


1. 标准写法的运行逻辑

First, here's the code again for reference:

for (var i = 0; i < 10; i++) { // Standard
  setTimeout(function() { console.log("Standard" + i); }, 1000 * i);
}

What's actually going on:

  • The for loop runs synchronously first. Since var is function-scoped (not block-scoped), there’s only one single i variable shared across the entire loop. By the time the loop finishes, i has incremented to 10 (the loop stops when i < 10 evaluates to false).
  • Each setTimeout schedules a callback function to run after 1000 * i milliseconds. But callbacks don’t execute immediately—they get queued in Node.js’s event loop. When each callback finally runs, it looks up the value of i... which is already 10 by then.
  • So your output will look like this:
    • After 0ms: Standard10
    • After 1000ms: Standard10
    • ... up to 9000ms: Standard10
  • Even though the callbacks fire at 1-second intervals (thanks to the 1000 * i delay), every log uses the final value of i.

2. IIFE写法的运行逻辑

Now let's break down the IIFE (Immediately Invoked Function Expression) version:

for (var j = 0; j < 10; j++) { // IIFE
  (function(j) { 
    setTimeout(function() { console.log("IIFE " + j); }, 1000 * j); 
  })(j);
}

What's different here?

  • The IIFE (function(j) { ... })(j) creates a new function scope for each loop iteration. When we pass j as an argument to the IIFE, we’re making a local copy of j that’s unique to that specific iteration.
  • Now, when setTimeout's callback runs, it "closes over" this local j variable from the IIFE’s scope—not the shared j from the loop. Since each IIFE has its own j (with the value from that loop iteration), the callback logs the correct number every time.
  • Your output will match what you’d expect:
    • After 0ms: IIFE 0
    • After 1000ms: IIFE 1
    • ... up to 9000ms: IIFE 9
  • Just like the standard loop, callbacks fire at 1-second intervals, but now each one uses the value of j from when it was scheduled.

Why does the IIFE fix the problem?

The core issue with the standard loop is that var doesn’t create block-scoped variables—so all callbacks reference the same single i. The IIFE fixes this by:

  • Spinning up a new function scope for every loop iteration.
  • Capturing the current value of j as a parameter in that scope, giving each setTimeout callback its own "private" variable to reference later.

As a quick side note: In modern ES6+ JavaScript, you could also fix this by swapping var for let in the loop. let is block-scoped and automatically creates a new variable for each iteration, making it a cleaner alternative to IIFEs these days!

内容的提问来源于stack exchange,提问作者Alberto Favaro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:12:30