由于js词法性质和全局变量被更改,循环绑定的click事件执行时变量和定义时 不一致的bug,各种解决方案。

由于js词法性质和全局变量被更改,循环绑定的click事件执行时变量和定义时 不一致的bug,各种解决方案。

动态在页面上添加了5个按钮,实现的功能应该是点击对应按钮在控制台输出相应的索引。但因为应该是i的变量应该一直指引的对应的地址,所以一直输出的是5.就是想请教您一下,这种问题应该是怎么样的一个解决思路。您要是有时间的时候帮我看下。非常感谢!

问题:

1 //这个有bug,一直输出5
2 for (var i =0 ; i<5 ; i++){
3 var btn = document.createElement("button");
4 btn.appendChild(document.createTextNode("Button"+i));
5 btn.addEventListener("click",function(){
6 console.log(i);
7 });
8 document.body.appendChild(btn);
9 }

错误解法一:

(虽然定义了新变量 ,避免了使用全局的i,但是,新变量一直被重新定义,最终定义为和最新的i保持一样了 )

 1     for (var i =0 ; i<5 ; i++){
 2     var btn = document.createElement("button");
 3     btn.appendChild(document.createTextNode("Button"+i));var j=i;
 4     btn.addEventListener("click",function(){
 5         console.log(j);
 6     });
 7     document.body.appendChild(btn);
 8 }
 9
10 //一直输出4

 错误解法二:

(所谓闭包)

 1 for (var i =0 ; i<5 ; i++){
 2     var btn = document.createElement("button");
 3     btn.appendChild(document.createTextNode("Button"+i));
 4     btn.addEventListener("click",function(){
 5         var result = function (num){
 6             return function(){
 7                 return num;
 8             }
 9         }(i);
10         console.log(result);
11     }
12     );
13     document.body.appendChild(btn);
14 }

 

解决方法一:
1 for (var i =0 ; i<5 ; i++){
2     var btn = document.createElement("button");
3     btn.appendChild(document.createTextNode("Button"+i));
4         btn.id="btn_"+i;
5     btn.addEventListener("click",function(){
6         console.log(this.id.split("_")[1]);
7     });
8     document.body.appendChild(btn);
9 }

解决方法二:

 1     for (var i =0 ; i<5 ; i++){
 2     var btn = document.createElement("button");
 3     !function(i){
 4     btn.appendChild(document.createTextNode("Button"+i));
 5     btn.addEventListener("click",function(){
 6         console.log(i);
 7     });
 8 }(i);
 9     document.body.appendChild(btn);
10 }

 1     for (var i =0 ; i<5 ; i++){
 2     var btn = document.createElement("button");
 3     (function(i){
 4     btn.appendChild(document.createTextNode("Button"+i));
 5     btn.addEventListener("click",function(){
 6         console.log(i);
 7     });
 8 })(i);
 9     document.body.appendChild(btn);
10 }

 总结:

 两种闭包方案,为何一个错,一个对?

 虽然都是闭包,但是你的没有把需要的东西给关闭进去,因为你的范围太小,你关时,人家已经是5 了。
 
两种正确做法有何区别?
而他们的写法是,在没成5时,就关闭进去,这样就保护了变量的中间值,他们存在闭包内,而另一种存在dom上,异曲同工之妙,都达到了中间值的保存。
 
posted @ 2016-10-12 15:03  齐楚燕韩赵魏秦  阅读(1069)  评论(0编辑  收藏  举报