日期:2014-05-16  浏览次数:20356 次

菜鸟请教关于闭包的问题
先上代码:
(1)html部分:
HTML code

<dl id="listContainer">
  <dt class="click">标题一</dt>
  <dd class="block">内容一</dd>

  <dt>标题二</dt>
  <dd>内容二</dd>

  <dt>标题三</dt>
  <dd>内容三</dd>

  <dt>标题四</dt>
  <dd>内容四</dd>
</dl>


(2)css部分:
CSS code

           *{ margin: 0;
              padding: 0;}

           dl{ width: 300px;
               margin: 100px auto;
               border: #666 1px solid;
               border-bottom: none;}
           dt{ line-height: 40px;
               background: #888;
               color: #fff;
               font-size: 14px;
               font-weight: bold;
               padding-left: 20px;
               border-top: #999 1px solid;
               border-bottom: #666 1px solid;
               cursor: pointer;}
           dt.click{ background: #dfdfdf;
                     color: #333;
                     border-bottom: #cfcfcf 1px solid;
                     border-top: #efefef 1px solid;}
           dd{ display:none;
               color: #444;
               font-size: 12px;
               text-align: center;
               padding: 20px;
               background: #efefef;}
           dd.block{ display: block;
                     border-bottom:#666 1px solid;
                     }


(3)脚本部分:
JScript code

  /*分别获取dt,dd标签组*/
  var listContainer=document.getElementById('listContainer'),
      dts=document.getElementsByTagName('dt'),
      dds=document.getElementsByTagName('dd');

  /*(在给点击的dt改变类名,相邻的dd改变类名之前)判断dt.click,dd.block是否存在并设置类名为空*/
  function disappear(){
    for(var n=0;n<dts.length;n++){
      if(dts[n].className=='click'){
        dts[n].className='';
      }
      if(dds[n].className=='block'){
        dds[n].className='';
      }
    }
  }

  /*主要函数---用于隐藏旧选项卡显示新选项卡*/
  function clickEffects(){
    for(var i=0;i<dts.length;i++){
      (function(){
        dts[i].onclick=function(){
          disappear();
          dt[i].className= (this.className!=='click')? 'click':'';
          dds[i].className= (this.className!=='block')? 'block':'';
        }
      })();
    }
  }
window.onload=clickEffects;



函数加载后执行失败。
测试后,该段代码的问题出在clickEffects函数中的匿名函数自执行部分,即:
JScript code

      (function(){
        dts[i].onclick=function(){
          disappear();
          dt[i].className= (this.className!=='click')? 'click':'';
          dds[i].className= (this.className!=='block')? 'block':'';
        }
      })();


之后,我将匿名函数引入参数,由i来递值,如下:
JScript code

      (function(num){
        dts[num].onclick=function(){
          disappear();
          this.className= (this.className!=='click')? 'click':'';
          dds[num].className= (this.className!=='block')? 'block':'';
        }
      })(i);


函数成功执行。

分析之后,发现在最初的未引用参数的匿名函数中:
匿名函数的i值为当前i值;
而匿名函数内部的匿名函数,即click绑定的函数中,i值为4(即i作为clickEffects局部变量在for循环之后的最终值).所以针对每次的click实际上是:
dt[0].onclick=function(){dts[4].className=......;dds[4].className=.....};
dt[1].onclick=function(){dts[4].className=......;dds[4].className=.....};
dt[2].onclick=function(){dts[4].className=......;dds[4].className=.....};
dt[3].onclick=function(){