运行下面这段代码,猜猜控制台会打印出什么
let i = 0 for(i = 0; i<6; i++){ setTimeout(()=>{ console.log(i) },0) }
你会发现控制台同时打印出6个6; 捋一下这段代码,声明变量i赋值为0后, 压栈,进入for函数; i=0,执行setTimeodsafut ,关键点来了; 由于setTimeout延迟时间是0,那么setTimeout会在当前任务执行完后再执行, console.log(i)等for执行完再执行; i=1,执行setTimeout,setTimeout说:“等for执行完”,此时参数i并没有传到setTimeout内 i=2,执行setTimeout,setTimeout说:“等for执行完” ,同上 i=3,执行setTimeout ,setTimeout说:“等for执行完”,同上 i=4,执行setTimeout,setTimeout说:“等for执行完”,同上 i=5,执行setTimeout,setTimeout说:“等for执行完”,同上 i=6,不满足i<6,退出for循环,一共执行了6次setTimeout, 此时,会直接执行setTImeout的内容,console.log(i);调用变量i=6,那么就是打印出6个6了~; setTimeout会把函数的调用时间往后退,在本例中,是推到for循环执行完成; 以上代码如何修改才能打印出0、1、2、3、4、5? 答案一 for 搭配let 把let i=0,放到for函数内部即可;
for(let i = 0; i<6; i++){ setTimeout(()=>{ console.log(i) },0)
但这只是JS给初学者的一块语法糖;按照阮一峰ES6入门教程 在for函数内部,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。 根据以上资料,我的理解是,此处for循环了6次,setTimeout接受了‘6个’i的指; 答案二 闭包 我尝试构造了一个xxx函数,形成闭包,在for循环执行中,首先,将实参i=0,setTimeout先传给xxx函数,然后延时调用函数。此时i=0作为函数xxx的实参保存在内存中,由于xxx当前无法执行完毕,所以他的实参i=0也就一直保存在内存中; for进入下一轮循环,i=1........ for函数执行完成 到达setTimeout所设定的时间后,xxx(1)执行,xxx(2)执行~ 5秒后调用参数xxx并令i=0; 5秒后调用参数xxx并令i=1;.... 再打印所有的cosole.log
let i = 0 for(i = 0; i<6; i++){ setTimeout(xxx.call(i,) ,5000) function xxx (){console.log(i)} }
以上仅基于目前我对JS闭包和JS函数执行时机和函数作用域的理解。如有纰漏,还望指正 ~