JS中For循环中嵌套setTimeout()的一些情况

大熙哥 2021年07月17日 149次浏览

JS中For循环中嵌套setTimeout()方法的执行顺序

function time() { 
  for(var i= 0;i<5;i++){ 
    setTimeout(function () { 
      console.log(i); 
    },1000) 
  } 
} 
time();

setTimeOut() 是一个异步函数。
JS的执行机制是单线程环境。
JS遇到异步函数的时候,会把异步函数插入到队列中等待。
由于setTimeOut()设置了一秒后才执行,所以插入的队列位置是一秒后。
用代码表示的话就是我们最开始设想的流程是这样的:
for(i=0) ——> console.log(0) ——> for(i=1) ——> console.log(1) ——> for(i=2) ——> console.log(2) ——> for(i=3) ——> console.log(3) ——> for(i=4) ——> console.log(4) ——> for(i=5) ——> 执行结束
但是在实际中的流程是这样的:
for(i=0) ——> for(i=1) ——> for(i=2) for(i=3) ——> for(i=4) ——> for(i=5)ps:(这段循环都在一秒内完成了)——> console.log(5) ——> console.log(5) ——> console.log(5) ——> console.log(5) ——> console.log(5) ——> 执行完成

解决方法

闭包,立即执行的函数表达式(IIFE)

for (var i = 0; i < 5; i++) { 
    (function (i) { 
        setTimeout(function () {
		console.log(i);
      }, 1000 * i)
    })(i) //这里使用闭包
}

立即执行函数是基于匿名函数实现的,也没有函数名,会在定义后立即执行; 闭包是有权访问另一个函数作用域中的变量的函数。 匿名函数、立即执行函数只要满足 有权访问另一个函数作用域中的变量 这一个条件,就成了闭包。

使用let,块级作用域

for (let i = 0; i < 5; i++) { 
    setTimeout(function() { 
        console.log(i)
    }, 1000 * i)
} 

JS中For循环中嵌套setTimeout(),延迟时间是0呢?

for (var i = 0; i <10; i++) {  
    setTimeout(function() {    // 同步注册回调函数到 异步的 宏任务队列。
         console.log(i)        // 执行此代码时,同步代码for循环已经执行完成
      }, 0)
}

setTimeout(function(),0) 也不是立马执行(特别是有耗时代码在前),这是因为 js 是单线程的,有一个事件队列机制,setTimeout 和 setInterval 的回调会到了延迟时间塞入事件队列中,排队执行。

setTimeout在若干毫秒后执行一个函数,并且是在for循环结束后。 for循环结束后,i的值为10。 所以当函数被调用的时候,它会打印出 10,其实道理是一样的。

setTimeout :延时 delay 毫秒之后,啥也不管,直接将回调函数加入事件队列。
setInterval :延时 delay 毫秒之后,先看看事件队列中是否存在还没有执行的回调函数( setInterval 的回调函数),如果存在,就不要再往事件队列里加入回调函数了。

JS的运行机制

运行机制

console.log("DIYXI");
setTimeout(function() {
  console.log("定时器");
}, 0);
Promise.resolve()
  .then(function() {
    console.log("promise1");
  })
  .then(function() {
    console.log("promise2");
  });
console.log("blog.diyxi.top");

#输出结果为
DIYXI
blog.diyxi.top
promise1
promise2
定时器

主线程 > 同步任务 > 微任务 > 宏任务