循环闭包
不知道这个问题大家有没有遇到过这种情况,for循环过程中永远输出最后一个值。反正我当年初学js的过程中遇到了,当时菜的时候问度娘,博客都差不多,就是看不懂。手动再见。
下面要实现的是,点击两个盒子,点击显示"这是第i个盒子"。
QAQ结果显示无论点击哪个盒子都是"这是第2个盒子"。
//html
<body>
<div></div>
<div></div>
</body>
//css
div {
background: pink;
width: 100px;
height: 100px;
margin-bottom: 10px;
}
//js
var divs = document.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener("click", function() {
alert("这是第" + i + "个盒子");
}, false);
}
其实仔细看看,就会发现问题。我们点击 div
触发事件,当代码执行到循环的时候,i = 0,1.. 到2跳出循环
这个时候相当于现在 i = 2
。
问题来了!!!
我只有点击div
的时候才能触发alert("这是第" + i + "个盒子");
啊! 所以,你无论怎么循环都是没有用的啊~
因为我们没点击啊~
当你点击 div
的时候,alert("这是第" + i + "个盒子");
中的i就不是循环的时候变量i啊,就只是一个普通的i=2
变量啊!
就是说整段for循环就跟我点击事件没太大关系啊~~
我就是给你提供了i=2
啊~~
解决办法
1、立即执行函数
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
(function(num) {
divs[i].addEventListener('click', function() {
alert("这是第" + num + "个盒子");
}, false);
})(i);
}
加入一个立即执行函数,注意 for (var i = 0; i < divs.length; i++) 后面的代码的写法(立即执行函数的写法)。
首先解释一下立即执行函数。
(function(){})();
简写(......)();
第一对括号内是一个函数体(表达式),这对括号仅用于划定表达式的范围;
第二对括号内是一个操作符,表示立即执行上面的表达式;而第二对括号内的值(如果有的话),就是执行上面表达式所需要的参数(也分实参、形参)。
为什么可以这么解决呢~道理就是循环的时候,每次循环都调用了 alert("这是第" + num + "个盒子");
事件啊~ 感觉就像提前定义好了,点击哪个div
,就弹出对应的。当我真正点击的时候,与之对应的弹出内容就来了,这就是我个人理解的观点。
现在大多数人的博客讲的都很深,对于菜鸟来说确实挺不好理解的。。
比如一个立即执行函数,我第一百度这个问题看到这个解决办法,一头雾水。。
其实写成下面这样应该会稍稍好理解一点。对我是这样子的~
点击事件封装成函数,调用函数。然后效果同上哈哈哈~
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
function ss(num) {
divs[i].addEventListener('click', function() {
alert(num);
}, false)
}
ss(i);
}
当然解决办法不光这一种,理解原因之后,一切都好办~
参考:http://www.cnblogs.com/Jerry-spo/p/6438792.html
本人仅代表个人观点。