We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
关于setTimeout,我之前的文章介绍过。setTimeout我们经常用来做延迟执行,那么setTimeout(fn,0),是不是就不延迟执行了!答案肯定是否定的。这篇文章,我详细介绍一下setTimeout(fn,0)及其应用。
for循环中有setTimeout,是我们在闭包案例中经常遇到和解决的一个问题,看一下下面这个案例
for (var i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, 0); console.log(i); }
对于上面的这个题目中的for循环和setTimeout结合,我之前文章中好像有写过,但是记不清在哪里写的了!这个题目的打印结果是什么呢?
对于这个题目,我们可以这么考虑,先把for循环里面的内容抽出来
setTimeout(function() { console.log(i); }, 0); console.log(i);
对于这个,肯定是先执行 console.log(i),后执行setTimeout。那么,我们把上面的for循环拆解开来,如下:
var i = 0; setTimeout(function() { console.log(i); }, 0); console.log(i); i++; setTimeout(function() { console.log(i); }, 0); console.log(i); i++; setTimeout(function() { console.log(i); }, 0); console.log(i); i++;
因为setTimeout是注册事件,要等到当前脚本的同步任务和“任务队列”中已有的事件,全部处理完以后,才能执行。因此,上面执行结果是把所有的console都执行完毕之后才能执行setTimeout,因此,执行结果如下:
0 1 2 3 3 3
这个我之前文章中好像有提及过,针对这种情况,我们将上面案例如下修改,就可以将setTimeout也可以输出1,2,3.
我们将setTimeout里面的匿名函数修改成自调用匿名函数
function() { console.log(i); }
修改成
(function(n) { console.log(n); })(i)
因为setTimeout的第一个参数必须是fn,因此,我们要对这个匿名函数返回一个function
(function(n) { return function() { console.log(n); }; })(i)
那么,代码如下:
for (var i = 0; i < 3; i++) { setTimeout((function(n) { return function() { console.log(n); }; })(i), 0); console.log(i); }
这样运行结果就是
0 1 2 0 1 2
我们看下面的运行结果
console.log(1); setTimeout(function() { console.log(2); }, 0); Promise.resolve().then(function() { console.log(3); }).then(function() { console.log(4); }); console.log(5); // 1 // 5 // 3 // 4 // 2
上面代码的执行结果说明,setTimeout(fn, 0)在Promise.resolve之后执行。这是因为setTimeout语句指定的是“正常任务”,即不会在当前的Event Loop(事件循环)执行。而Promise会将它的回调函数,在状态改变后的那一轮Event Loop(事件循环)指定为微任务。所以,3和4输出在5之后、2之前。
setTimeout(fn, 0)的一大应用是,可以调整事件的发生顺序。比如,网页开发中,某个事件先发生在子元素,然后冒泡到父元素,即子元素的事件回调函数,会早于父元素的事件回调函数触发。如果,我们先让父元素的事件回调函数先发生,就要用到setTimeout(fn, 0)。
案例如下:
document.getElementById("haoroomsID").onclick = function A() { setTimeout(function B() { console.log("触发子元素事件") }, 0) }; document.body.onclick = function C() { console.log("触发父元素事件") };
上面案例,点击haoroomsID会先触发父级元素事件,然后再触发子元素事件。
关于setTimeout(fn,0)就先写到这里,有关Event Loop(事件循环)的相关文章,请看:http://www.ruanyifeng.com/blog/2014/10/event-loop.html
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
关于setTimeout,我之前的文章介绍过。setTimeout我们经常用来做延迟执行,那么setTimeout(fn,0),是不是就不延迟执行了!答案肯定是否定的。这篇文章,我详细介绍一下setTimeout(fn,0)及其应用。
案例分析
for循环中有setTimeout,是我们在闭包案例中经常遇到和解决的一个问题,看一下下面这个案例
对于上面的这个题目中的for循环和setTimeout结合,我之前文章中好像有写过,但是记不清在哪里写的了!这个题目的打印结果是什么呢?
分析
对于这个题目,我们可以这么考虑,先把for循环里面的内容抽出来
对于这个,肯定是先执行 console.log(i),后执行setTimeout。那么,我们把上面的for循环拆解开来,如下:
因为setTimeout是注册事件,要等到当前脚本的同步任务和“任务队列”中已有的事件,全部处理完以后,才能执行。因此,上面执行结果是把所有的console都执行完毕之后才能执行setTimeout,因此,执行结果如下:
for循环和setTimeout
这个我之前文章中好像有提及过,针对这种情况,我们将上面案例如下修改,就可以将setTimeout也可以输出1,2,3.
我们将setTimeout里面的匿名函数修改成自调用匿名函数
修改成
因为setTimeout的第一个参数必须是fn,因此,我们要对这个匿名函数返回一个function
那么,代码如下:
这样运行结果就是
应用
我们看下面的运行结果
上面代码的执行结果说明,setTimeout(fn, 0)在Promise.resolve之后执行。这是因为setTimeout语句指定的是“正常任务”,即不会在当前的Event Loop(事件循环)执行。而Promise会将它的回调函数,在状态改变后的那一轮Event Loop(事件循环)指定为微任务。所以,3和4输出在5之后、2之前。
setTimeout(fn, 0)的一大应用是,可以调整事件的发生顺序。比如,网页开发中,某个事件先发生在子元素,然后冒泡到父元素,即子元素的事件回调函数,会早于父元素的事件回调函数触发。如果,我们先让父元素的事件回调函数先发生,就要用到setTimeout(fn, 0)。
案例如下:
上面案例,点击haoroomsID会先触发父级元素事件,然后再触发子元素事件。
扩展阅读
关于setTimeout(fn,0)就先写到这里,有关Event Loop(事件循环)的相关文章,请看:http://www.ruanyifeng.com/blog/2014/10/event-loop.html
The text was updated successfully, but these errors were encountered: