for(var i=0;i<8;i++){ setTimeout(function () { console.log(i) },0) }
输出了8次8,这跟js的执行顺序和作用域链有关。
规则:
同步优先、异步靠边、回调垫底。
用公式表达就是:同步 => 异步(定时器 or 异步请求) => 回调
1、js同步执行与异步执行
js的执行机制: js是单线程环境,从上到下、依次执行,即 同步执行;在这段代码中,for循环是同步代码,setTimeout是异步代码。
js在执行代码的过程中,碰到同步代码会依次执行,碰到异步代码就会将其放入任务队列中进行等待,当同步代码执行完毕后再开始执行异步代码,即 异步执行。
2、js作用域问题
当同步代码执行完毕后,开始执行异步的setTimeout代码,执行setTimeout时需要从当前作用域内寻找一个变量 i ,此时for循环已执行完毕,当前 i=8,所以执行setTimeout时输出为8,任务队列中的剩余7个setTimeout也依次执行,输出为8。
3、常用解决方法
利用立即执行函数,当for循环执行时,就会立即执行setTimeout,从而使得到的每个副本i值都不一样,这样就可以得到想要的for循环的结果。如:
for(var i=0;i<8;i++){ (function (x) { setTimeout(function () { console.log(x) },0) })(i); }
参考:
https://blog.csdn.net/ld767416042/article/details/84030668
https://www.cnblogs.com/wangwenhui/p/7657654.html
https://blog.csdn.net/huakaiwuxing/article/details/78968642
https://baijiahao.baidu.com/s?id=1621653715044760064&wfr=spider&for=pc
https://blog.csdn.net/u010297791/article/details/71158212
https://blog.csdn.net/jssy_csu/article/details/78627628