混淆了函数参数,闭包和范围链之间的交互

时间:2013-02-21 16:15:47

标签: javascript variables closures

有问题的代码:

    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应该保持当前值替换旧值并且应该使用该值自动更新到处。但这不会发生 - 当我点击每个链接时,我得到一个不同的值。为什么会这样?

5 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分: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);
    }
}

乍一看,您可能希望,例如,因为您在i = 0时在第一个链接上分配了点击处理程序,所以当您点击它时它会发出警告0。但是,当您点击它时,它实际上会提醒3

你自己说,你的代码正在创建一个闭包。上面的代码是它为每个链接的click事件分配一个函数处理程序。每个函数处理程序都维护对变量i的引用(注意:不是它的当前值!)。

在分配函数处理程序时,它实际上不会评估i具有什么值(因为它不需要它)。当您点击,aha时,它会检查i的值是什么并提醒它。

当您点击链接时,您的for循环将会很长时间完成,并显示i = 3,这就是您的点击处理程序提醒的内容。

答案 2 :(得分:0)

请在功能后查看(i)。这种表示法仅适用于自调用功能。这就像你设置link.onclick =一个数字,而它需要一个函数。您只需使用以下内容即可。

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

请注意,默认情况下,点击功能会将“事件”作为参数接收。确保你调用事件的preventDefault()方法,否则它会冒出DOM并因锚元素的性质而触发回发。

答案 3 :(得分:0)

您尚未解释变量num的来源或使用方式。我猜你的意思是警告i的当前值。 click处理程序将一个事件对象作为参数,所以我会这样尝试:

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;

答案 4 :(得分:0)

这很奇怪,并且不同意我对封闭的了解。唯一的变化(在问题的addLinks的第一个版本中):

link.onclick = function (num)

link.onclick = function ()

您将获得预期结果,即,在单击链接时随时会提醒全局num变量的实际值。

它可能与解释器在遇到闭包时如何保存闭包内引用的作用域变量有关。当在闭包中引用变量时,将搜索该变量最接近的位置,从当前作用域向上移动。

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

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