js闭包-在你身边却不知
今天组里小伙很纳闷的问了我js绑事件带出的一个小问题,随便聊聊闭包那点事,背景如下:
当点击Button的时候给li绑定事件,事件的大概内容是获取li位置的index再做点事,据他描述代码看上去也没错,就是index一直是最后一个值
UI代码:
<button id="btnAttach"></button> <ul id="ulTarget"> <li>我是第一个</li> <li>我是第二个</li> <li>我是第三个</li> <li>我是第四个</li> </ul>
js代码:
$("#btnAttack").bind("click", function(){ var a = $("#J_memberslide").find("li"); for(var i=0;a && i<a.length;i++){ $(a[i]).bind("click", function(){ alert(i); }); }
a=null; });
当然demo代码是精简过的示意代码,大概意思是点击按钮后,让ul下的li绑定click事件,click事件的内容是输出当前li的positioin的index值。
代码结果:点击任意一个li,输出都是3
代码分析
按钮事件内,通过循环的方式给每个li对象绑定了事件,事件的主体为一匿名函数,这里的匿名函数就成了一个闭包,在匿名函数内部引用了外部的变量i, 当函数执行时输出i的值
问题
为什么当点击触发匿名事件时,i的值一直是3
答案
当按钮事件绑定时,闭包引用的外部变量i的值并未被闭包访问,仅引用了变量i,即当循环绑定结束后i的值为3,而不绑定时取到i的值并保存,这是关键。
当li被点击时匿名函数才去访问变量i的值,即3,所以所有li点击时都输出的3
总结
闭包是JS经典特色之一,当它在你身边不必惊慌,也不要忽略