JS闭包的特性,for循环 setTimeout()的秘辛
2023-11-04 00:40:39
在深入讨论之前,我们先明确一下setTimeout()函数。setTimeout()函数是一个异步函数,它允许您在指定的毫秒数后执行一个函数或一段代码。它是window对象的属性,属于Web API的一部分。当调用setTimeout()时,它会返回一个ID,该ID用于识别超时(setTimeout)并可以在将来使用clearTimeout()函数清除它。
在 for 循环中使用 setTimeout() 会创建一个闭包,闭包是一个函数及其周围状态(包括它的词法作用域)的组合。闭包允许函数访问和修改其创建时周围的变量,即使这些变量在函数返回后已经超出了其作用域。
为了更好地理解在 for 循环中使用 setTimeout() 时会发生什么,让我们看一个具体的例子:
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
在这个例子中,我们使用一个 for 循环来创建一个闭包,这个闭包包含了变量 i 和函数 console.log()。当 for 循环执行时,它会为每个值i创建一个新的闭包,这些闭包被存储在内存中,即使for循环已经执行完毕。
当 setTimeout()被调用时,它会创建一个新的定时器,该定时器会在指定的毫秒数后(在本例中为1000毫秒)执行闭包。在这个例子中,当定时器触发时,它会执行闭包,而闭包会访问并记录变量 i 的值。
需要注意的是,在 for 循环中使用 setTimeout() 时,变量 i 是一个共享变量,它会在闭包中被捕获。这意味着当闭包被执行时,它会访问并记录变量 i 的当前值,而不是它在 for 循环中被创建时的值。
这就是为什么在上面的例子中,当定时器触发时,它会记录 0 到 4 的值,即使 for 循环已经执行完毕。这是因为闭包捕获了变量 i 的值,并且在定时器触发时,变量 i 的值为 4。
在 for 循环中使用 setTimeout() 时要注意几个要点:
- 闭包会捕获变量 i 的值,即使 for 循环已经执行完毕。
- 当定时器触发时,闭包会访问并记录变量 i 的当前值,而不是它在 for 循环中被创建时的值。
- 可以使用 let 或 const 来避免这种情况。let 和 const 关键字会创建块级作用域变量,这些变量只在块的作用域内可用。这可以防止变量 i 在 for 循环中被共享。
希望这篇文章能帮助您理解在 for 循环中使用 setTimeout() 时会发生什么。