今天在写js的时候, 我需要在for循环中为一个列表中的每一项元素设置onclick属性, 每个元素的点击作用不同, 大概是这样的情况:
window.onload = function(){
var list = document.getElementById("menu");
for(var i in collection){
var item = document.createElement("li");
item.innerHTML = collection[i]["nomCommun"];
item.onclick = function(){
var box = document.getElementById("details");
box.innerHTML="";
var pic = document.createElement("img");
pic.src = "images/"+collection[i]["photo"];
box.appendChild(pic);
}
list.appendChild(item);
}
};
我要给我的每一个 li 加一个 onclick 属性, 让他们点击的时候根据json中的路径地址来在box中加载对应的图片, 但是我发现结果我得到的是不论点击哪个 li 得到的都是最后一个元素对应的图片;
找到原因发现: 在每一次 li 被click的时候都会去执行一遍collection[i]["photo"]
来获取图片路径但是其实此时for循环已经执行完毕, i的值已经停留在了最后一个元素的坐标位置上, 所以不论如何点击获取到的都是最后一个元素的图片地址;
那么为什么会发生这个情况呢, 我们看一下, 每当onclick被触发的时候, 会去调用我提供的匿名函数function然后在运行到这一行的时候:
pic.src = "images/"+collection[i]["photo"];
它会在自己的作用域内寻找变量i, 发现没有找到, 所以就去外部变量中找到到了 i 变量, 所以我们要改变这一情况, 只需要在它匿名函数内部提供一个变量域来存储一个 i 的值, 比如我们可以这样做:
window.onload = function(){
var list = document.getElementById("menu");
for(var i in collection){
var item = document.createElement("li");
item.innerHTML = collection[i]["nomCommun"];
addOnclick(item, i);
list.appendChild(item);
}
};
function addOnclick(item, x){
item.onclick = function(){
var box = document.getElementById("details");
box.innerHTML="";
var pic = document.createElement("img");
pic.src = "images/"+collection[x]["photo"];
box.appendChild(pic);
}
}
这样做就让函数function有了一个独立的作用域;
再回头看一下, 这个function其实既要访问外部的自由变量, 又希望能拥有自己的独立变量域, 这不正是闭包的定义么 哈哈哈:
window.onload = function(){
var list = document.getElementById("menu");
for(var i in collection){
var item = document.createElement("li");
item.innerHTML = collection[i]["nomCommun"];
(function(){
var x = i;
item.onclick = function(){
var box = document.getElementById("details");
box.innerHTML="";
var pic = document.createElement("img");
pic.src = "images/"+collection[x]["photo"];
box.appendChild(pic);
}
})();
list.appendChild(item);
}
};
然后也可以通过块作用域来实现, 使用let/const:
window.onload = function(){
var list = document.getElementById("menu");
for(var i in collection){
let ii = i ;
var item = document.createElement("li");
item.innerHTML = collection[i]["nomCommun"];
item.onclick = function(){
var box = document.getElementById("details");
box.innerHTML="";
var pic = document.createElement("img");
pic.src = "images/"+collection[ii]["photo"];
box.appendChild(pic);
}
list.appendChild(item);
}
};