javascript闭包

今天在写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);
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值