首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > JavaScript >

初学者请问关于闭包的有关问题

2012-11-10 
菜鸟请教关于闭包的问题先上代码:(1)html部分:HTML codedl idlistContainerdt classclick标题一

菜鸟请教关于闭包的问题
先上代码:
(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(){dts[4].className=......;dds[4].className=.....};
因为dts[4]和dds[4]是不存在的,所以函数最终执行失败。

而我的疑虑也正在于此:


其实,click绑定的函数中,i=4这个很好理解,作为闭包取clickEffects活动对象的最终值。但是,为什么在其外部的匿名函数中,i的值不总等于4而是取了i的当前值0,1,2,3?这个外部的匿名函数该怎么对待,难道不是clickEffects的闭包?

[解决办法]
闭包我也不懂,帮顶顺便接分
[解决办法]
function clickEffects(){
for(var i=0;i<dts.length;i++){
(function(num){
dts[i].onclick=function(){
disappear();
dt[i].className= (this.className!=='click')? 'click':'';
dds[i].className= (this.className!=='block')? 'block':'';
}
})(i);
}
}
window.onload=clickEffects;
我来解释下,给添加的外层匿名函数的i是实参,是for循环中的i,当for循环中的i=0,这个i就作为实参传给num这个形参并立即执行,num是一个局部变量,之所以没有消失是因为 dts[i].onclick=function(){
disappear();
dt[i].className= (this.className!=='click')? 'click':'';
dds[i].className= (this.className!=='block')? 'block':'';
}函数引用了外层函数的变量i,当循环多次就产生多个内部函数,每个内部函数都分别引用外部相应的i
[解决办法]
因为for里面的匿名函数并没有形成闭包,匿名函数跟onclick定义的函数的区别就在于i什么时候会被用到。
你把函数改成这样就好理解一些

JScript code
function clickEffects(){    for(var i=0;i<dts.length;i++){      (function(){        alert(i);       }      })();    }  } 

热点排行
Bad Request.