当闭包遇上for

  看看这个函数先:

      function fun1(x) {

        var a = x;   //a为局部变量

        function fun2() {

          return a;

         }

         return fun2;

        }

      var fun3 = fun1(10);

      var fun4 = fun1(9);

      alert(fun4()); //9

      alert(fun3()); //10

      a = 99;     //此时的a定义在全局环境下

      alert(fun3()); //10

  看出来没?fun3与fun4其实是通过闭包函数绑定了fun1的局部私有变量,同时fun3与fun4其实引用的闭包是不同的,但在内存合理分配的角度上看,更准确的说fun3与fun4的区别在于引用同一闭包函数时传入闭包函数的参数值是不同的,也就是说,我们可以通过参数来看函数的执行。

  我们可以这样说:fun3是存储了a为10的引用的闭包调用,fun4是存储了a为9的引用的闭包调用。

所以,以下的输出就不难理解了:

  window.onload = function(){

    var oUl = document.getElementsByTagName("ul");

    var aLi = oUl.getElementsByTagName("li");

    var l = aLi.length;

    for( i =l - 1 ; i >= 0 ; i--){    

      aLi[i].onclick = function (){

        alert(i);

    }

  }

  此时点击li的结果都是弹出aLi.length的值,假设aLi.length为4,分析如下~

  原因是:js中,函数可通过调用而在不同时刻执行,时间由我们定,但对于for,if等流程控制语句其实是逐行进行的,也就是说当点击li触发onclick函数时,for循环已经结束,此时i值为4,所以点击时传入闭包的值为4,也就是说此时传入要调用的闭包的变量值为4,所以结果皆为4。我们之所以会有疑惑,大部分都是因为觉得传入的参数是aLi[i]中的i,其实此时传入的是for执行完时的 i 的引用;

  我是这样想的,通过for给aLi标序并添加onclick存放参数值为 i 的闭包的引用,此时传入的 i 为全局变量,for执行结束,i 为4,所以要为各li 在局部锁定相应 i 值,才能输出想要的结果,这时就要利用到闭包的特性了。

  看看怎么解决吧:

    window.onload = function(){

      var oUl = document.getElementsByTagName("ul");

      var aLi = oUl.getElementsByTagName("li");

      var l = aLi.length;

       for( i =l - 1 ; i >= 0 ; i--){

          aLi[i].onclick = function (a){

              return function(){

                alert(a);

              }

           }(i);

       }

    }

  将aLi[i]的 i 当为参数传入内部函数,也就是说将 i 当做参数通过function (a)中的a传入return出来的闭包,此时alert(a);中的a与传入的 i 同值。实现了“绑定”,得到了想要的结果~

  当然,问题的解决方法往往不止一个,分清楚希望传入闭包的变量是什么往往可以更快的找到解决方案。

  

  

posted @ 2014-04-09 15:19  Pada  阅读(159)  评论(0编辑  收藏  举报