好像是第二次遇到这个问题,必须要总结一下!!
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title></title> 6 </head> 7 <style type="text/css"> 8 li{ 9 100px; 10 height: 50px; 11 background-color: red; 12 margin-bottom: 10px; 13 } 14 </style> 15 <body> 16 <ul id="ulList"> 17 <li></li> 18 <li></li> 19 <li></li> 20 <li></li> 21 </ul> 22 <script> 23 var lis = document.getElementById("ulList").getElementsByTagName("li"); 24 for(var i=0;i<lis.length;i++){ 25 lis[i].onclick = function(){
console.log(i);
}30 } 31 </script> 32 </body> 33 </html>
如果按照以上方法,无论点击哪一个li标签,i的值都会是4,并不能像我们所想的那样打印出0,1,2,3,原因是什么呢?
暂时也不太清楚,好像涉及闭包,因为也没学到,就参考别人回答总结一下。
for循环是一个外部闭包,依次绑定的点击事件是一个函数实例,也产生了一个闭包域,它引用了外部闭包的变量i,外部闭包域中i的最终值为4,点击事件触发时引用外部闭包变量i(此时i=4),所以输出的值全为4。
暂时先写两种自己能掌握的解决方法:
方法一:在for循环中点击事件外套一个自执行的匿名函数,将索引变量i保存到匿名函数的形参中
1 <script> 2 var lis = document.getElementById("ulList").getElementsByTagName("li"); 3 for(var i=0;i<lis.length;i++){ 4 (function(arg){ 5 lis[i].onclick = function(){ 6 console.log(arg); 7 } 8 })(i); 9 } 10 </script>
方法二:在for循环中,为每一个要点击的对象创建属性用来保存索引变量i
1 <script> 2 var lis = document.getElementById("ulList").getElementsByTagName("li"); 3 for(var i=0;i<lis.length;i++){ 4 lis[i].i = i; //创建属性保存变量i 5 lis[i].onclick = function(){ 6 console.log(this.i); 7 // console.log(lis[i].i);绝对不能这样写,要不然 Uncaught TypeError: Cannot read property 'i' of undefined 8 } 9 } 10 </script>