【问题标题】:Javascript closure and its scopeJavascript 闭包及其作用域
【发布时间】:2013-03-25 12:51:39
【问题描述】:
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 ?它应该alert 4 .alerting 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?

【问题讨论】:

  • 当您在当前迭代中将参数i 传递给具有参数num 的内部onclick 函数时,它会在单击第一个元素时发出警报1
  • This question on SO 有一些很好的答案可以帮助你理解闭包
  • 它实际上应该是警报 0,因为那是你传递的第一个 #

标签: javascript closures


【解决方案1】:
  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 在传递给外部函数时是一个。然后 i 在循环的每一轮中被迭代,并且对于每个链接将是不同的值。

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

【讨论】:

  • 那么事件处理程序不会在第一次点击时引用 arg num 吗?
  • 是的。并且 num 被闭包保留为第一次设置 onclick 属性时 i 的值。
【解决方案2】:

您所做的是避免点击第一个元素会得到 4 而不是 1 的经典示例,这应该是最期望的值。

如果您希望它提醒 1,那么只需执行以下操作:

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

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

【讨论】:

    猜你喜欢
    • 2018-09-09
    • 2017-06-18
    • 2010-12-20
    • 2010-10-12
    • 2014-08-29
    • 2011-01-19
    • 2014-02-13
    • 2013-01-01
    • 1970-01-01
    相关资源
    最近更新 更多