Javascript闭包及其范围

时间:2013-04-03 17:48:09

标签: javascript closures

for (var i=0, link; i<5; i++) {
    link = document.createElement("a");
    link.innerHTML = "Link " + i;
    link.onclick = function (num) {
        return function () {
            alert(num);
        };
    }(i);
    document.body.appendChild(link);
}

由于嵌套函数是一个闭包,它有一个对num参数的引用,循环结束时的num参数是4.当第一个元素被点击时,为什么它会发出警报1?它应该警告4。警报1的原因是什么?不引用num参数?或者是什么原因?

但这里的情况有所不同:

function foo(x) {
    var tmp = 3;
    return function (y) {
       alert(x + y + (++tmp));
    }
}
var bar = foo(2); // bar is now a closure.
bar(10);

上面的函数会提醒16,因为bar仍然可以引用arg xtmp,即使它不再直接在范围内。

这证明了闭包还引用了参数值,而不是为什么上面的代码每次都没有提醒4?

2 个答案:

答案 0 :(得分:3)

  for (var i=0, link; i<5; i++) {  //i starts at 0 and iterates up to 4
        link = document.createElement("a");
        link.innerHTML = "Link " + i;


         link.onclick = function (num) {
            //num is never changed within this function, and is equal
            //to the value of i when it was passed in

            return function () { alert(num);};

        }(i);  //i is passed here
        //that sets num to the current value of i for each link

        document.body.appendChild(link);
   }

对于第一个链接,num将为0,因为i在传递给外部函数时为1。然后,我会循环每次循环,并且每个链接的值都不同。

这里的模式是一种非常常见的模式,用于保留回调/事件绑定中循环迭代的当前值。

答案 1 :(得分:0)

你正在做的是避免的经典例子,点击第一个元素会给你4而不是1,这应该是最期望的值。

如果您希望它提醒1,那么就这样做:

link.onclick = function() {alert(i);};

但老实说,这有什么意义呢?所有4个链接都会提醒4 ...

相关问题