函数执行时机不同,结果就不同。

  1. let i = 0
  2. for(i = 0; i<6; i++){
  3. setTimeout(()=>{
  4. console.log(i)
  5. },0)
  6. }

问:为什么最后会输出6个6?
答:setTimeout ()函数可以理解为尽快执行,也就是执行完当前手头的任务再执行setTimeout()函数。当for循环遇上setTimeout()函数时,先执行完for循环,再执行setTimeout()。上述代码,for循环结束时i=6,且共执行了6次,所以setTimeout()函数在for循环结束后,也会执行6次,所以最后的输出结果是6个6。

写出让上面代码打印 0、1、2、3、4、5 的方法


方法一:临时变量

  1. let i;
  2. for(let i = 0; i< 6; i++){
  3. let j=i
  4. setTimeout(()=>{
  5. console.log(j)
  6. },0)
  7. }

词法作用域根据源代码中声明变量的位置来确定该变量在何处可用

方法二:let 放在 for 里面

  1. for(let i = 0; i < 6; i++){
  2. setTimeout(()=>{
  3. console.log(i)
  4. },0)
  5. }

因为let将i绑定到for循环中,将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的箭头函数属于一个新的域,通过var定义的变量是无法传入到这个函数执行域中的,通过使用let来声明块变量能作用于这个块,所以箭头函数就能使用i这个变量了;利用了箭头(匿名)函数的参数作用域和for循环的参数作用域不一样。

方法三:setTimeout()的第三个参数

setTimeout()的第三个参数会被传到setTimeout()的回调函数中

  1. let i = 0
  2. for (i = 0; i < 6; i++) {
  3. setTimeout((value)=> {
  4. console.log(value );
  5. }, 0, i );
  6. }

方法四:立即执行函数

  1. let i = 0
  2. for ( i=0; i < 6; i++) {
  3. (function(value) {
  4. setTimeout(()=> {
  5. console.log( value );
  6. }, 0 );
  7. })(i);
  8. }

将i的变量驻留在内存中,当输出value时,引用的是外部函数的变量值i,i的值是根据循环来的,执行setTimeout()时已经确定了里面的的输出了。