由于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上,异曲同工之妙,都达到了中间值的保存。