".forEach循环:使用变量"

4

我正在循环遍历一组16个ID,并为每个ID分配一个eventListener。 我想向我的php文件发送一个数字(第一个ID为1,第二个为2等等),但似乎i比我想要的更加动态。 每个ID都发送17

klasses.forEach(function(klass){
    var svgElement = svgDoc.getElementById(klass); //get the inner element by id
    svgElement.addEventListener("mouseup",function(){
        $.ajax({
            type: "POST",
            url: "buildService.php",
            data: { "service" : i}
        }).done(function(msg){
            alert(lameArray[i]);
            $("#modalSpan").html(msg);
            $("#modmodal").modal();
        });
    });
    i++;
});

我该如何将每一个设置为特定的数字?我也尝试过以下方法:
var lameArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
...
data: { "service" : lameArray[i]}

阅读JavaScript闭包属性... - scusyxx
3个回答

10

什么是i?问题在于i是一个全局变量,或者至少是在forEach循环之外的变量,所以当触发mouseup事件时,使用的是那个时刻i的值,而不是事件监听器被定义时的值。

请注意,由于您正在使用forEach,回调函数实际上会带有第二个参数,即计数器。因此,您可以使用:

klasses.forEach(function(klass, i) {
    ...
});
现在,iforEach作用域中的变量,并且可以满足您的目的。(forEach调用回调函数时还使用第三个参数,即集合本身 - 在您的情况下是klasses。) 注意:由于您正在使用jQuery,因此应以更“jQuery风格”的方式编写代码。因此,请将您的代码更改为以下内容:
$.each(klasses, function(i, klass) {
    $("#" + klass).mouseup(function(){
        $.ajax({
            type: "POST",
            url: "buildService.php",
            data: {service: i + 1}
            ...
        });
    });
});

1

试试这个:

klasses.forEach(function(klass){
    (function(i) {
        var svgElement = svgDoc.getElementById(klass); //get the inner element by id
        svgElement.addEventListener("mouseup",function(){
            $.ajax({
                type: "POST",
                url: "buildService.php",
                data: { "service" : i}
            }).done(function(msg){
                alert(lameArray[i]);
                $("#modalSpan").html(msg);
                $("#modmodal").modal();
            });
        });
    })(i);
    i++;
});

另一方面,您可以将代码中的第一行更改为 klasses.forEach(function(klass, i){ - jagm
1
为什么不使用for循环而使用forEach呢? - Bergi
1
Bergi所说的是,如果您在每次迭代时都需要调用一个函数,则可以使用forEach,并将回调函数中的第二个参数作为计数器。 - MaxArt
@Bergi:首先,我使用了问题中的一部分代码。其次,在我看来,forEach比for循环更具有友好的语法。是的,我知道并非所有浏览器都支持forEach。 - jagm
@MaxArt:我知道,所以我添加了第一条评论。 - jagm

1

当你需要迭代器索引时,请勿使用forEach。并避免使用JQuery的.each方法。大多数情况下完全不必要,并且它在每次迭代中触发回调函数,因此在IE上速度较慢。您可以编写一个非常懒惰/紧凑的循环,而不使用这些方法。

var outerI = klasses.length;

while(outerI--){
    (function(i){
        i+=1;//doesn't affect outerI and you wanted 1-length so we add one.
        //I would personally just add 1 but it also adds clarity to the example

        //crap inside your forEach loop but without the i++
    })(outerI)
}

发生了什么:您告诉事件侦听器引用外部作用域中的 i。因此,当该事件发生时,i 的值就是您获得的值。
解决方案:将 i 的值传递到函数的作用域中,其中它变成一个局部变量。带圆括号的业务只是一种懒惰的方式,在似乎只有一步的情况下定义、评估和执行一个匿名函数。函数通过第一个圆括号进行评估(使其可以被触发),所以第二组类似于您放入函数定义的内部“i”参数的参数。通过将它传递给新的本地变量,您正在锁定所需的值。
关于 while 循环的说明:while(0) 评估为 false,停止循环。如果您考虑过这个问题,这很奇怪,因为长度到1比您想要的少1。但是,用 while(i--),i 被评估,然后 i 被减小,因此在块内,您得到从 length-1 到 0 的范围,这对于数组符号来说非常完美。为了在其他运算符击中 i 之前减少 i,通常会使用 --i,但在懒惰/高效的 while 循环中,这很方便。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接