意外行为:Javascript、setTimeout() 和 IIFE
Unexpected behavior: Javascript, setTimeout(), and IIFE
Javascript、事件循环、setTimeout、IIFE、闭包
根据下面的参考,我对以下代码的理解是:
setTimeout() 是非阻塞的,由浏览器 Web APIs 处理,它在计时器完成时将回调放在回调队列中。然后事件循环等待调用栈空闲,依次运行每个回调。 setTimeout 闭包关闭匿名 IIFE,并且每次迭代都有正确的索引值。
for(var i = 0; i < 3; i++){
(function(index){
setTimeout(function(){
console.log(index);
}, 5000);
})(i);
console.log("loop="+i);
}
/*Output in console is
loop=0
loop=1
loop=2
//after 5 seconds
0
1
2
*/
我正在寻找 Chrome.
中以下代码所发生情况的解释
for (var i = 0; i < 3; i++) {
setTimeout(
function(index) {
console.log(index);
}(i), 5000
);
console.log("loop="+i);
}
/* Output in console without any delay is:
0
loop=0
1
loop=1
2
loop=2
*/
为什么 'console.log(index)' 立即执行,没有 5 秒的延迟?
Web API 如何作为 IIFE 执行带有回调的 setTimeout()?
回调队列中是否有回调?
事件循环是否将任何回调移动到调用堆栈?
或者 setTimeout() 是否被忽略并立即在调用堆栈上执行其回调?
我查阅过的参考资料:
Philip Roberts:事件循环到底是什么? | JSConf 欧盟 2014
https://www.youtube.com/watch?v=8aGhZQkoFbQ
Philip Roberts 帮助我陷入事件循环 2016
https://www.youtube.com/watch?v=6MXRNXXgP_0
调用堆栈和事件循环
https://www.youtube.com/watch?v=mk0lu9MKBto
JavaScript closure inside loops – simple practical example
Use IIFE in setTimeout in a loop, but why?
在
setTimeout(
function(index) {
console.log(index);
}(i), 5000
);
您正在立即调用传递给setTimeout
的第一个参数。当解释器遇到 setTimeout
行时,它首先尝试将其所有参数解析为值。第一个参数是一个函数调用,因此它调用该函数是为了预期它将解析为 另一个 函数 - 就像一个人可以做的那样
setTimeout(makeFn('foo'), 5000);
其中 makeFn
return 是一个函数。
因此,在您的代码中,
function(index) {
console.log(index);
}(i)
立即运行,但它不会 return 任何东西 - 解释器将 setTimeout
行解析为
setTimeout(undefined, 5000);
但是 undefined
不是一个函数,所以没有任何异步排队。
这里没有任何 IIFE - 将整个 setTimeout
行放在 IIFE 中:
for (var i = 0; i < 3; i++) {
((i) => {
setTimeout(
function() {
console.log(i);
}, 500
);
console.log("loop=" + i);
})(i);
}
(或者,当然,使用 const
或 let
而不是 var
- 最好避免 var
,它的提升和功能范围非常不直观,需要for
循环中的冗长解决方法)
for (let i = 0; i < 3; i++) {
setTimeout(
function() {
console.log(i);
}, 500
);
console.log("loop=" + i);
}
在第二个示例中,您没有将函数传递给 setTimeout
,而是传递函数调用的结果(在本例中为空)。
function(index) {
console.log(index);
}(i)
你看,在这个例子中你的函数会立即调用,因此以后没有什么可调用的,控制台日志按顺序显示。
I'm looking for an explanation of what's happening with the following
code in Chrome.
for (var i = 0; i < 3; i++) {
setTimeout(
function(index) {
console.log(index);
}(i), 5000
);
console.log("loop="+i);
}
/* Output in console without any delay is:
0
loop=0
1
loop=1
2
loop=2
*/
考虑以下语句:
function(index) {
console.log(index);
}(i)
这是一个匿名函数并立即执行(末尾的括号“()”执行该函数):参见语法function(param) {...}()
。所以效果是每次迭代上面的代码都会立即执行。
结果是(如您所见):
0
1
2
setTimeout at MDN。方法需要一个 function(在 定时器到期后执行)或 code 作为它的第一个参数。在这种情况下,您有立即执行的代码(不是函数)。因此,您会立即看到结果。
延迟5秒没有效果,没用过。延迟之后就没有什么可执行的了。
Firefox 也是一样的效果
你可以试试匿名函数末尾没有括号的代码,看看会发生什么:
function(index) {
console.log(index);
}
函数将在延迟五秒后执行,在这种情况下!
Javascript、事件循环、setTimeout、IIFE、闭包
根据下面的参考,我对以下代码的理解是:
setTimeout() 是非阻塞的,由浏览器 Web APIs 处理,它在计时器完成时将回调放在回调队列中。然后事件循环等待调用栈空闲,依次运行每个回调。 setTimeout 闭包关闭匿名 IIFE,并且每次迭代都有正确的索引值。
for(var i = 0; i < 3; i++){
(function(index){
setTimeout(function(){
console.log(index);
}, 5000);
})(i);
console.log("loop="+i);
}
/*Output in console is
loop=0
loop=1
loop=2
//after 5 seconds
0
1
2
*/
我正在寻找 Chrome.
中以下代码所发生情况的解释for (var i = 0; i < 3; i++) {
setTimeout(
function(index) {
console.log(index);
}(i), 5000
);
console.log("loop="+i);
}
/* Output in console without any delay is:
0
loop=0
1
loop=1
2
loop=2
*/
为什么 'console.log(index)' 立即执行,没有 5 秒的延迟?
Web API 如何作为 IIFE 执行带有回调的 setTimeout()?
回调队列中是否有回调?
事件循环是否将任何回调移动到调用堆栈?
或者 setTimeout() 是否被忽略并立即在调用堆栈上执行其回调?
我查阅过的参考资料:
Philip Roberts:事件循环到底是什么? | JSConf 欧盟 2014 https://www.youtube.com/watch?v=8aGhZQkoFbQ
Philip Roberts 帮助我陷入事件循环 2016 https://www.youtube.com/watch?v=6MXRNXXgP_0
调用堆栈和事件循环 https://www.youtube.com/watch?v=mk0lu9MKBto
JavaScript closure inside loops – simple practical example
Use IIFE in setTimeout in a loop, but why?
在
setTimeout(
function(index) {
console.log(index);
}(i), 5000
);
您正在立即调用传递给setTimeout
的第一个参数。当解释器遇到 setTimeout
行时,它首先尝试将其所有参数解析为值。第一个参数是一个函数调用,因此它调用该函数是为了预期它将解析为 另一个 函数 - 就像一个人可以做的那样
setTimeout(makeFn('foo'), 5000);
其中 makeFn
return 是一个函数。
因此,在您的代码中,
function(index) {
console.log(index);
}(i)
立即运行,但它不会 return 任何东西 - 解释器将 setTimeout
行解析为
setTimeout(undefined, 5000);
但是 undefined
不是一个函数,所以没有任何异步排队。
这里没有任何 IIFE - 将整个 setTimeout
行放在 IIFE 中:
for (var i = 0; i < 3; i++) {
((i) => {
setTimeout(
function() {
console.log(i);
}, 500
);
console.log("loop=" + i);
})(i);
}
(或者,当然,使用 const
或 let
而不是 var
- 最好避免 var
,它的提升和功能范围非常不直观,需要for
循环中的冗长解决方法)
for (let i = 0; i < 3; i++) {
setTimeout(
function() {
console.log(i);
}, 500
);
console.log("loop=" + i);
}
在第二个示例中,您没有将函数传递给 setTimeout
,而是传递函数调用的结果(在本例中为空)。
function(index) {
console.log(index);
}(i)
你看,在这个例子中你的函数会立即调用,因此以后没有什么可调用的,控制台日志按顺序显示。
I'm looking for an explanation of what's happening with the following code in Chrome.
for (var i = 0; i < 3; i++) {
setTimeout(
function(index) {
console.log(index);
}(i), 5000
);
console.log("loop="+i);
}
/* Output in console without any delay is:
0
loop=0
1
loop=1
2
loop=2
*/
考虑以下语句:
function(index) {
console.log(index);
}(i)
这是一个匿名函数并立即执行(末尾的括号“()”执行该函数):参见语法function(param) {...}()
。所以效果是每次迭代上面的代码都会立即执行。
结果是(如您所见):
0
1
2
setTimeout at MDN。方法需要一个 function(在 定时器到期后执行)或 code 作为它的第一个参数。在这种情况下,您有立即执行的代码(不是函数)。因此,您会立即看到结果。
延迟5秒没有效果,没用过。延迟之后就没有什么可执行的了。
Firefox 也是一样的效果
你可以试试匿名函数末尾没有括号的代码,看看会发生什么:
function(index) {
console.log(index);
}
函数将在延迟五秒后执行,在这种情况下!