js闭包问题的解决(立即执行函数)

题目:想要打印出0,1,2,3,4,5,6,7,8,9 ,但是由于闭包它们会打印出10 10 10 10 10 10 10 10 10 10 :



function test(){
   var arr = [];
   for(var i = 0; i < 10; i ++){
       arr[i] = function(){
           document.write(i + " ");
       }
   }
   return arr;
}

var myArr = test();
for(var j = 0; j < 10; j++){
   myArr[j]();
}
//myArr [0]();
//myArr [1]();
//myArr [2]();
//myArr [3]();
//myArr [5]();
//myArr [6]();
//myArr [7]();
//myArr [8]();
//myArr [9]();

//10 10 10 10 10 10 10 10 10 10 

解析 :往arr数组添加十条数据,让它的每一条数据都是一个function,
   	  由于function在函数内部,那么每一个function都和test形成了一个闭包。
   	  
   	  arr[i] = function(){
           document.write(i + " ");
       }
      
   	arr[i]每次循环都在变,arr[0],arr[1],arr[2]。。。
   	每一次变化都让它等于一个全新的函数体, function(){ document.write(i + " ");  }。 
   	这是一条赋值语句,arr[i] = 函数,系统在读到这里的时候,系统把这个函数当做一个引用来看,系统也不知道内部是什么,内部document.write(i + " ");里面的i不会改变,这个地方只是函数定义的位置,它不在当前位置执行,它在外部执行。 
    然后把数组返回到外部,就是说把这十个函数体都一起保存到了外部。
    到了外部有一个操作,分别执行十个函数体,执行这十个函数体的时候才会回来找现在的i是多少。
    因为test函数已经执行完了之后,i的值就为10,它们十个函数还共用一个test的执行期上下文,每个函数就会去执行期上下文里面找 i,就都会打印10

解决方法: 上面那个是十对一的状态,就是十个函数对应一个test的执行期上下文。
解决方法:用立即执行函数将十对一变成一对一的闭包。


function test(){
   var arr = [];
   for(var i = 0; i < 10; i ++){

       (function(j){
           arr[j] = function(){
               document.write(j + " ");
           } 
       }(i));
   }
   return arr;
}

var myArr = test();
for(var j = 0; j < 10; j++){
   myArr[j]();
}

解析:
1,for循环每一次循环都执行一个立即执行函数,
将i作为参数传给每个立即执行函数,
所以每一次j是从0到9,arr[j]就会变成
js闭包问题的解决(立即执行函数)_第1张图片
2,

arr[1] = function(){
         document.write(j + " ");
           }

这个函数每次执行arr[1] = function(){ document.write(j + " ");}里面的j是不会被赋值 的,因为它是一个函数的声明,还没有被执行。

3,

 (function(j){
              arr[j] = function(){
                document.write(j + " ");
            } 
        }(i));

这样的 function(){document.write(j + " "); }和它所对应的立即执行函数形成一对一的闭包, 这个函数就会拿到它对应的立即函数的劳动成果,这样arr[j]就会等0,1,2,3,4。。。
然后等待立即执行函数被执行完毕之后要被销毁,但是arr[j]已经被保存到了test函数的内部,放到了arr数组里面,并且当十个立即执行函数都执行完之后,arr数组又被保存到了test函数的外部,这样执行myArr的时候是执行的 function(){document.write(j + " "); },因为立即执行函数已经被销毁,所以这个函数就会自动去找自己所对应的立即执行函数的上下文里面的j.这样就是十个一对一的闭包。

你可能感兴趣的:(javascript)