luk*_*act 2 javascript settimeout
我一直在查看 StackOverflow 上已经发布的答案,但没有一个是令人满意的。他们都给出了问题的实际解决方案,但这并不能解决我的问题。
看看这个例子:
for(var i = 1; i <= 5; i++) {
setTimeout(function(){
console.log(i)
}, 1000);
}
Run Code Online (Sandbox Code Playgroud)
这是一个经典的例子,它总是会产生:
6
6
6
6
6
Run Code Online (Sandbox Code Playgroud)
这一切都很好。我的理解是 for 循环运行并设置 5 个超时以在 1 秒后运行。当 1 秒过去后,setTimeout 内的函数将运行。由于这是 1 秒,因此我很快就会得到值 6。
所以我尝试了别的东西。如果我将超时设置为 0 毫秒会怎么样?这会改变结果吗?
for(var i = 1; i <= 5; i++) {
setTimeout(function(){
console.log(i)
}, 0);
}
Run Code Online (Sandbox Code Playgroud)
不,没有。
6
6
6
6
6
Run Code Online (Sandbox Code Playgroud)
这毫无意义。为什么异步 setTimeout 函数只有在for 循环完成后才运行。我什至尝试设置 for 循环值 i <= 50000,但结果仍然相同。这毫无意义。在我看来,一旦 1ms 过去,setTimeout 就会调用该函数,无论它是否在 for 循环内。有人可以向我解释一下吗?谢谢,我读了无数的媒体、stackoverflow 和博客文章,但仍然没有点击。范围解释也没有帮助。
因为var是吊装的。var当您在循环中定义 a 时for,该变量将在循环顶部定义for。
var i = undefined;
for(i = 1; i <= 5; i++) {
setTimeout(function(){
console.log(i)
}, 1000);
}
Run Code Online (Sandbox Code Playgroud)
的回调函数setTimeout与变量形成一个闭包i。当执行回调时,闭包就被解决了。由于每次for迭代都会注册一个回调,该回调将在循环退出后进行计算for,因此 的值i就是6此时的值。
您应该使用它let而var不是块作用域且不提升的。receive的每次迭代for都有自己的迭代i,它将与回调形成闭包。这样,您将收到想要的结果。
for(let i = 1; i <= 5; i++) {
setTimeout(function(){
console.log(i)
}, 1000);
}
1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)
事件循环是浏览器(或 Node)中的一个在后台持续运行的软件。它的工作是向 JavaScript 引擎(例如 Chrome 中的 V8)提供回调函数来执行。该setTimeout函数是浏览器提供的 Web-API,它将回调函数发送到(事件队列)任务队列以在 JavaScript 引擎内执行。
事件循环从任务队列中选择一个回调并将其推送到 JavaScript 引擎的调用堆栈上,但它只能在调用堆栈为空时执行此操作。每次for循环迭代都会将setTimeout调用推送到执行它的调用堆栈。因此,除非完成所有 for 循环迭代,否则调用堆栈永远不会为空。因此,任务队列中排队的所有回调最终都会被执行。您选择什么时间打电话并不重要setTimeout。
链接我写了这篇Medium 文章,详细讨论了事件循环。
| 归档时间: |
|
| 查看次数: |
1503 次 |
| 最近记录: |