函数执行时机不同,结果就不同。
let i = 0for(i = 0; i<6; i++){setTimeout(()=>{console.log(i)},0)}
问:为什么最后会输出6个6?
答:setTimeout ()函数可以理解为尽快执行,也就是执行完当前手头的任务再执行setTimeout()函数。当for循环遇上setTimeout()函数时,先执行完for循环,再执行setTimeout()。上述代码,for循环结束时i=6,且共执行了6次,所以setTimeout()函数在for循环结束后,也会执行6次,所以最后的输出结果是6个6。
写出让上面代码打印 0、1、2、3、4、5 的方法
方法一:临时变量
let i;for(let i = 0; i< 6; i++){let j=isetTimeout(()=>{console.log(j)},0)}
词法作用域根据源代码中声明变量的位置来确定该变量在何处可用
方法二:let 放在 for 里面
for(let i = 0; i < 6; i++){setTimeout(()=>{console.log(i)},0)}
因为let将i绑定到for循环中,将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的箭头函数属于一个新的域,通过var定义的变量是无法传入到这个函数执行域中的,通过使用let来声明块变量能作用于这个块,所以箭头函数就能使用i这个变量了;利用了箭头(匿名)函数的参数作用域和for循环的参数作用域不一样。
方法三:setTimeout()的第三个参数
setTimeout()的第三个参数会被传到setTimeout()的回调函数中
let i = 0for (i = 0; i < 6; i++) {setTimeout((value)=> {console.log(value );}, 0, i );}
方法四:立即执行函数
let i = 0for ( i=0; i < 6; i++) {(function(value) {setTimeout(()=> {console.log( value );}, 0 );})(i);}
将i的变量驻留在内存中,当输出value时,引用的是外部函数的变量值i,i的值是根据循环来的,执行setTimeout()时已经确定了里面的的输出了。
