This question already has answers here:
Javascript infamous Loop issue? [duplicate]
                                
                                    (5个答案)
                                
                        
                        
                            JavaScript closure inside loops – simple practical example
                                
                                    (44个回答)
                                
                        
                5年前关闭。
            
        

我正在使用JavaScript和HTML画布制作游戏。 “加载”功能完美运行而无需for循环。但是“加载”在for循环中变得有问题且不合理。但是,我想出了一个简单的解决方法来跳过该问题。但是我仍然很好奇为什么。以下是代码以及解决方法:

我创建了一个对象:

function Monster() {
    this.image = new Image();
    this.ready = false;
}


并创建了几个(假设两个)实例:

var monster = [];
for(var a = 0; a < 2; a++) {
    monster.push(new Monster());
}


当我尝试初始化这些对象时,它将失败:

for(n = 0; n < monster.length; n++) { //assume length is 2
    monster[n].image.onload = function() {
        monster[n].ready = true;   /* Problem raise up here, n has the same value as monster.length.
                                      If length is 2, this line gonna run 2 times */
    };
    monster[n].image.src = 'images/m1.png';
}


但是,可以通过创建一个函数轻松解决此问题:

for(n = 0; n < monster.length; n++) {
    makeMonster(n);
}


和:

var makeMonster = function(n) {
    monster[n].image.onload = function() {
        monster[n].ready = true;
    };
    monster[n].image.src = 'images/m1.png';
};


问题是,为什么?

最佳答案

onload函数是异步的,因此到它触发时,循环已经完成,并且n的值是它最后设置的值。

您必须使用闭包将n变量的值锁定在新作用域中,创建新函数也将创建此类作用域,或者类似这样

for(n = 0; n < monster.length; n++) {
    (function(k) {
        monster[k].image.onload = function() {
            monster[k].ready = true;
        }
        monster[k].image.src = 'images/m1.png';
     })(n);
}

10-05 21:04
查看更多