代码改变世界

深入理解JavaScript系列阅读笔记(4):立即调用的函数表达式

2013-04-05 08:22  极乐鸟  阅读(295)  评论(0编辑  收藏  举报

关于原文中的用闭包保存状态

// 所以说无论点击那个连接,最终显示的都是I am link #10(如果有10个a元素的话)

var elems = document.getElementsByTagName('a');

for (var i = 0; i < elems.length; i++) {

    elems[i].addEventListener('click', function (e) {
        e.preventDefault();
        alert('I am link #' + i);
    }, 'false');

}

最终结果都显示为I am link #10(如果有10个a元素的话),这是作用链域的分配机制导致的。从表面上看,似乎每次点击某个连接的时候都应该返回自己的索引值。即点击位置为0的链接应该返回0,点击位置为1的链接应该返回1,以此类推。但实际上,点击每个链接都返回链接数的最大值,这是因为每个elems[i].addEventListener

他们都保存着全局的活动对象,所以他们引用的都是同一个变量i(按引用传递)。

解决方法:通过创建另一个匿名函数,强制使结果符合预期。

var elems = document.getElementsByTagName('a');

for (var i = 0; i < elems.length; i++) {

    (function (lockedInIndex) {

        elems[i].addEventListener('click', function (e) {
            e.preventDefault();
            alert('I am link #' + lockedInIndex);
        }, 'false');

    })(i);

}

这里匿名函数有一个参数lockedInIndex,也就是点击连接时最终要返回的结果值,在调用匿名函数时,我们传入了变量i,由于函数的变量是按值传递的,所以会将当前变量的值复制给lockedInIndex,所以最终我们能够得到预期的结果。