免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1682 | 回复: 0
打印 上一主题 下一主题

理解JavaScript闭包 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-16 16:21 |只看该作者 |倒序浏览
  1. <ul>   
  2.         <li>1111</li>   
  3.         <li>2222</li>           
  4.         <li>3333</li>
  5. </ul>
  6. <script>
  7.         var a=document.getElementsByTagName('li');
  8.         for(var i=0,l=a.length;i<l;i++){        
  9.                 a[i].onclick=function(){            
  10.                         alert(i)        
  11.                 }   
  12.         }
  13. </script>
复制代码
一个最经典的例子,上面的代码无论点击哪个结果都为最后的值,因为click事件接收的函数形成了一个闭包,闭包里的i只是对外部函数中变量i的引用,当fn执行完毕时变量i是循环得出的最后的值,闭包内的变量i也就是这个值了,所以不会依次弹出1,2.3.

至于解决的方法:

1)为遍历的每个元素添加自定义属性用来保存当前的索引值.
  1. function fn() {
  2.     var a = document.getElementsByTagName("li ");
  3.     for( var i=0; i<a.length; i++ ) {
  4.         a[i].i = i;
  5.         a[i].onclick = function() {
  6.             alert(this.i);
  7.         }
  8.     }
  9. }
复制代码
2)将当前索引值保存到匿名函数自身.
  1. function fn() {
  2.     var a = document.getElementsByTagName("li");
  3.     for( var i=0; i<a.length; i++ ) {
  4.         (a[i].onclick = function() {
  5.             alert(arguments.callee.i);
  6.         }).i = i;
  7.     }
  8. }
复制代码
3)加一层闭包,将当前索引值以函数参数形式传递到内部函数.
  1. function fn() {
  2.     var a = document.getElementsByTagName("li");
  3.     for( var i=0; i<a.length; i++ ) {
  4.         (function(arg){
  5.             a[i].onclick = function() {
  6.                 alert(arg);
  7.             };
  8.         })(i);//调用时参数
  9.     }
  10. }
复制代码
4)加一层闭包,将当前索引值以变量形式传递到内不函数.
  1. function fn() {
  2.     var a= document.getElementsByTagName("li");
  3.     for( var i=0; i<a.length; i++ ) {
  4.         (function () {
  5.             var index = i;//调用时局部变量
  6.             a[i].onclick = function() {
  7.                 alert(index);
  8.             }
  9.         })();
  10.     }
  11. }
复制代码
5)加一层闭包,返回一个函数作为响应事件.
  1. function fn() {
  2.     var a = document.getElementsByTagName("li");
  3.     for( var i=0; i<a.length; i++ ) {
  4.         a[i].onclick = function(arg) {
  5.             return function() {//返回一个函数
  6.                 alert(arg);
  7.             }
  8.         }(i);
  9.     }
  10. }
复制代码
6)利用Function对象,需要注意的是Function构造函数是在脚本运行时创建函数并将参数用作新函数的参数,所以相对前几种方法执行效率较低.
  1. function fn() {
  2.     var a = document.getElementsByTagName("li");
  3.     for( var i=0; i<a.length; i++ ) {
  4.         a[i].onclick = Function('alert('+i+')')
  5.     }
  6. }
复制代码
7)利用Function对象实例来产生闭包.
  1. function fn() {
  2.     var a= document.getElementsByTagName("li");
  3.     for( var i=0; i<a.length; i++ ) {
  4.         a[i].onclick = new Function('alert(' +i+' )' );//new一次就产生一个函数实例
  5.     }
  6. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP