Javascript 被函数参数、闭包和范围链之间的交互弄糊涂了

Javascript 被函数参数、闭包和范围链之间的交互弄糊涂了,javascript,variables,closures,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(n

有关守则:

    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;
link.onclick = function (num)
函数addLinks(){

对于(var i=0,link;i请查看函数后面的(i)。这种类型的表示法仅适用于自开票函数。这就好像您正在设置link.onclick=一个数字,而它需要一个函数。您可以简单地使用以下方法

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

请注意,默认情况下,click函数将“event”作为参数接收。请确保调用事件的preventDefault()方法,否则,由于锚元素的性质,它将弹出DOM并触发回发。

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

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

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

函数(var varname)
是无效语法。

您没有解释变量
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;
var links = $('a');
for (var i = 0; i < links.length; i++) {
    links[0].onclick = function () {
        alert(i);
    }
}
函数addLinks(){

对于(var i=0;i想想看:如果你有三个这样的链接怎么办:

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

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

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;
var links = $('a');
for (var i = 0; i < links.length; i++) {
    links[0].onclick = function () {
        alert(i);
    }
}
var links=$('a');
对于(变量i=0;i
乍一看,您可能希望,例如,由于您在
i=0
时在第一个链接上分配了click处理程序,因此当您单击它时,它将发出警报
0
。但是,当您单击它时,它实际上会发出警报
3

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

当您分配函数处理程序时,它实际上不会计算
i
的值(因为它不需要)。当您单击时,aha,它会检查
i
的值并向其发出警报


当你点击一个链接时,你的
for
循环将很长时间结束,
i=3
,这就是你的点击处理程序提醒你的。

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

您将得到预期的结果,即当单击链接时,会随时通知全局
num
变量的实际值

这可能与解释器在遇到闭包时如何保存闭包中引用的范围变量有关。当在闭包中引用变量时,将搜索该变量最接近的匹配项,以从当前范围向上搜索

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


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

你在说什么,你不在主题范围内先生“好像你正在设置link.onclick=a数字”不,它不是——它是将其设置为函数。我不理解您的问题。在控制台中执行第一个版本的
addLinks
,然后单击它添加的链接,每次发出不同值的警报时都会产生结果。这对您来说是意外行为吗?@Marcell Fülöp yaa完全意外,因为num是一个全局变量,其值为s每次使用函数时都应该更改或更新runs@Maizerenum不是全局变量。定义函数参数时不需要使用
var
关键字-它们隐式地位于该函数的本地。@Marcell Fülöp感谢您提供的信息。我认为num是一个全局变量。HTML元素没有
.on
方法。是的,您是对的——得到了jQuery与此有关。我很抱歉。因此您可以将其切换回link.onclick=function(event){alert(i);};感谢您指出:-)