js for循环问题解析

问题原因

  首先让我们来看一段代码

 function foo(){
  for (var i = 0;i<3;i++){
    console.log(i)
  }
}
 function foo1(){
  for (var i = 0;i<3;i++){
     setTimeout( function timer() { console.log( i ); }, i*1000 );
  }
}
foo() //0 1 2 
foo1() // 3 3 3

  foofoo1同样是for循环。为什么一个输出0 1 2,一个输出3 3 3呢?而我们希望 foo1 也输出 0 1 2该怎么解决呢?这个就与 js 的作用域相关了。当var声明变量是不会有块级作用域的,上述代码相当于。

function foo(){
 {
   var i = 0
    console.log(i)
 }
 {
  var  i = 1 
    console.log(i)
  }
 {
  var  i = 2 
    console.log(i)
  }
  {
  var  i = 3//终止循环了
  }
}

function foo1(){
 {
   var  i = 0
    setTimeout( function timer() { console.log( i ); }, i*1000 );
 }
 {
  var  i = 1 
    setTimeout( function timer() { console.log( i ); }, i*1000 );
  }
 {
 var   i = 2 
    setTimeout( function timer() { console.log( i ); }, i*1000 );
  }
  {
  var  i = 3//终止循环了
  }
}
foo() //0 1 2 
foo1() // 3 3 3

如上述代码,foo会输出 0 1 2,就很好理解。foo1()遇到setTimeout,setTimeout内部的函数会放到循环执行完毕之后去执行它。而这时 i 的值 已经是 3了所以他们会输出3 3 3。解决这个问题很好解决,因为我们知道是因为 var 没有产生块级作用域。

解决方法1

所以我们用let就阔以解决它了。

function foo1(){

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

}
foo1(); //0 1 2

那么假如我们不想使用let,该如何解决呢?也有办法。

解决方法2

function foo1(){

for (var i=0; i<3; i++) { 
  (function(j) { 
    setTimeout( 
      function timer() { 
        console.log( j ); 
       }, j*1000 ); 
  })( i );
  }
}
foo1(); //0 1 2

我们利用立即执行函数去接收i, 函数内部作用域中,j就是i的值,不会i的改变影响。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。