4

有问题的代码:

    function addLinks () {
    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);
    }
  }
  window.onload = addLinks;

我的问题是,因为返回的函数是一个闭包,而变量num是每次函数执行时的全局变量,num应该保持当前值替换旧值,并且应该在任何地方自动更新该值。但这并没有发生——当我单击每个链接时,我会得到不同的值。为什么会这样?

4

5 回答 5

2

num被匿名函数关闭。按原样function (num) { return function () {}}(i)传递给内部函数,并根据当时的值返回一个新函数。ii

如果您希望点击回调始终提醒 的最大值i,实际上更简单:

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

function (var varname)只是无效的语法。

于 2013-02-21T16:23:31.097 回答
1

想一想:如果你有三个这样的链接怎么办:

<a href="#">0</a>
<a href="#">1</a>
<a href="#">2</a>

您希望他们在您单击它们时提醒他们的号码,因此您可以这样做:

var links = $('a');
for (var i = 0; i < links.length; i++) {
    links[0].onclick = function () {
        alert(i);
    }
}

乍一看,你会期望,例如,因为你在第一个链接上分配了点击处理程序 when ,它会在你点击它时发出i = 0警报。0但是,当您单击它时,它实际上会发出警报3

您自己说过,您的代码正在创建一个闭包。上面的代码所做的是将函数处理程序分配给每个链接的单击事件。这些函数处理程序中的每一个都维护对变量的引用i(注意:不是当前值!)。

在您分配函数处理程序时,它实际上并不评估i具有什么值(因为它不需要它)。当您单击时,啊哈,那是它检查具有什么值i并发出警报的时候。

当您单击一个链接时,您的for循环将完成很长时间,并带有i = 3,这就是您的单击处理程序发出的警报。

于 2013-02-21T16:29:55.557 回答
0

请查看您的函数后的 (i)。这种类型的符号仅用于自调用函数。就好像您正在设置 link.onclick = 一个数字,而它需要一个函数。您可以简单地使用以下内容。

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

请注意,点击函数默认接收“事件”作为参数。确保调用事件的 preventDefault() 方法,否则由于锚元素的性质,它会冒泡 DOM 并触发回发。

于 2013-02-21T16:23:21.080 回答
0

您还没有解释变量num的来源或使用方式。我猜你的意思是提醒i. 点击处理程序将事件对象作为参数,所以我会这样尝试:

function addLinks () {
for (var i=0; i<5; i++) {
    var link = document.createElement("a");
    link.innerHTML = "Link " + i;
    link.onclick = function (event) {
            alert(i);
    };
    document.body.appendChild(link);
}
}
window.onload = addLinks;
于 2013-02-21T16:26:44.740 回答
0

这很奇怪,与我认为对闭包的了解不一致。唯一的变化(在addLinks问题的第一个版本中):

link.onclick = function (num)

link.onclick = function ()

您会得到预期的结果,即在num任何时候单击链接时都会提示全局变量的实际值。

它可能与解释器在遇到闭包时如何保存在闭包中引用的范围变量有关。当一个变量在闭包中被引用时,从当前范围向上搜索该变量最接近的出现。

虽然在第一种情况下,它被定义为参数(对于在多次声明后调用的函数),但它每次都有不同的值,因此每个闭包“记住”不同的范围值。

在第二种情况下,发现的唯一事件是在全局范围内,这导致num无论调用哪个处理程序,都会使用 的实际值。

于 2013-02-21T16:45:51.953 回答