wangjie-fourth 的个人博客

记录精彩的程序人生

目录
JS 函数的执行时机
/  

JS 函数的执行时机

let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
// 666666

以上代码其实等价于

var i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
// 
for(var i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

三种方法得出来得结果都是666666,为什么不是 0-5 呢?

答案是:在 i = 0 时,由于 js 是异步运行机制,导致当 setTimeout 计时的过程中,for 循环继续在执行,又因为 for 循环的执行时间远远小于计时时间,所以 for 的循环完成即 i = 6。当 i = 0 时,开启一个定时, i = 1 时又开启一个定时,i=2 时开启一个定时,所以开启了 6 个定时,当第一个定时时间到了之后 for 循环执行了 6 次,开启了 6 个定时,所以 i = 6,后面的定时器就会按照开启的间隔时间依次输出 6

解决办法

1、let方式

for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

2、闭包方式
将每次定时函数得i, i 的值传入了闭包内,不会由于 for 循环的继续执行而被污染,外部的 for 循环的 i 值不会影响闭包内部的值。

for (var i = 0; i < 6; i++) {
    (function (j) { 
        setTimeout(function() { 
            console.log(j); 
        }, 0); 
    })(i); 
}

3、使用立即执行函数
但这样定时函数后面得参数,就没什么意义了

for (var i = 0; i < 6; i++) { 
	setTimeout((function () { 
		console.log(i); 
	})(),i*1000);
评论