2

本页讨论臭名昭著的循环问题:

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

一个解决方案:

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;

这是我的问题:如果您正在调用的函数在父函数之外(例如,在 addLinks 之外),臭名昭著的循环问题仍然是一个问题吗?

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

我认为这会是因为当 onclick 被作为函数调用时 addLinks 尚未创建,所以问题已被创建。因此,将函数放在 addLInks 之外应该可以缓解臭名昭著的循环问题,不是吗?

4

3 回答 3

4

您的代码中的问题是它不起作用。

link.onclick = Outside(i);

不绑定函数,因为Outside(i)返回未定义。

一个类似的工作解决方案是定义Outside

function Outside(i) {
    return function() {
       alert(i);
    }
};

它的工作原理与您的第二个代码工作的原因相同:调用该函数Outside会为变量创建一个新范围i(称为闭包)。

您将从循环构建的任何解决方案可能不仅仅涉及函数调用:它需要使用var关键字或作为该函数的参数来声明变量。

于 2013-03-27T20:44:40.630 回答
2
link.onclick = Outside(i);

这实际上将调用Outside(i)而不是将侦听器设置为等于具有该默认值的该函数。诸如 Ext 之类的各种工具包提供了一种创建代表的方法,类似于 dystroy 所展示的。例如,在 Ext 3.X 中,您可以这样做:

link.onclick = Outside.createDelegate(link, [i]) 创建一个委托,该委托具有link上下文thisi默认参数Outside

要使您的示例正常工作,您需要执行以下操作:

function Outside(i) {
    return function() { alert(i); }
};
于 2013-03-27T20:46:22.637 回答
2

我相信你写的代码不会运行。

外面不返回任何东西。所以调用 Outside(i) 将返回 undefined。这意味着您正在设置 link.onclick=undefined。

于 2013-03-27T20:46:51.413 回答