【转】很多JavaScript初学者都会搞错的问题
关键词:循环 闭包 事件绑定
JavaScript入门门槛很低,整几条语句就能给页面添加一些交互行为(比如点击某个按钮并alert一句“欢迎访问我的主页”)。就拿这个绑定事件来说,稍不注意就会出现行为与你的预期不一致的情况。
假设页面上有若干个链接,点击每个链接都弹出特定的一句话,那么你的代码很可能是这么写的。
var say = ["这是第一句话", "这是第二句话", "这是第三句话"];
for (var i = 0; i < 3; i ++) {
var a = document.getElementById("a" + i);
a.onclick = function(){alert(say[i])};
}
上面的代码把所有话放在say数组里,然后循环给每个a元素绑定事件,以便点击时弹出相应的话。一切看上去很直观,没有什么问题,但是实际情况是什么呢?你会发现弹出来都是“undefined”。那么正确的写法应该是:
for (var i = 0; i < 3; i ++) {
var a = document.getElementById("a" + i);
(function(){
var index = i;
a.onclick = function(){alert(say[index])};
})();
}
为什么上面的写法会出现undefined呢,这个和JavaScript的closure有关系,也就是onclick的函数中的那个变量i引用自其父函数,当你点击a的时候,那个i的值已经随着for循环执行而变化了,i的最终值为3,所以访问say[3]当然就是undefined了。后面的解决方法是再增加一个closure来保存每一次的i值,使之固定下来,这样就不会出现问题了。
closure是JavaScript中非常重要的概念,应该好好掌握一下。