2010-12-11 5 views
0

Cas simple: Je souhaite charger plusieurs images ayant un nom commun et un suffixe, par exemple: image0.png, image1.png, image2.png ... imageN.pngFermetures dans un environnement en boucle et lexical

J'utilise une simple boucle:

var images = []; 
for (var i=1; i<N; i++) { 
    images[i] = new Image(); 
    images[i].onload = function() { 
     console.log("Image " + i + " loaded"); 
    }; 
    images[i].src = "image" + i + ".png"; 
} 

ce que je veux dans la console est:

Image N loaded 
Image N loaded 
Image N loaded 
... 
Image N loaded 

Mais ce que je veux devrait ressembler à ceci:

Image 0 loaded 
Image 1 loaded 
Image 2 loaded 
... 
Image N loaded 

Pourquoi cela se produit-il? Comment puis-je obtenir le comportement souhaité?

+0

double possible de [fermeture Javascript boucles à l'intérieur - exemple simple pratique] (http://stackoverflow.com/questions/750486/javascript-closure -inside-loops-simple-pratique-exemple) –

Répondre

3

Le i intérieur de votre fonction est évaluée lorsque la fonction est exécutée , pas lorsque vous attribuez à onload. Votre boucle for est déjà terminée au moment où l'une de vos fonctions onload se déclenche, de sorte que tous voient la valeur finale N.

Pour capturer la valeur actuelle de i, vous devez passer comme paramètre à une autre fonction où il peut être capturé comme une variable locale:

function captureI(i) { 
    return function() { 
     console.log("Image " + i + " loaded"); 
    }; 
} 

var images = []; 
for (var i=1; i<N; i++) { 
    images[i] = new Image(); 
    images[i].onload = captureI(i); 
    images[i].src = "image" + i + ".png"; 
} 

Cela fonctionne parce que chaque fois que vous appelez captureI, un Une nouvelle variable locale est créée pour cette instance de captureI. En substance, vous créez N différentes variables et chaque fonction onload capture une instance différente de la variable.

+0

Merci pour la dernière explication. –

0

Votre variable de compteur de boucle a déjà été remplacée. Check out this FAQ entrée expliquant exactement pourquoi cela arrive et comment contourner le problème.

0

Puisque la variable i est déclarée en dehors de la portée de la boucle, elle conserve sa valeur finale une fois la boucle terminée. Les fonctions anonymes que vous créez se lient toutes à cette variable et lorsqu'elles sont appelées, elles ont toutes la même valeur finale de N.

Il y a une bonne discussion à ce sujet dans this question.

+0

cela donnera N-1 pour toutes les images :-) –

2

Vous pouvez envelopper dans une fermeture pour éviter d'utiliser la variable i, qui est une variable de boucle et passe ainsi:

(function(j) { 
    images[i].onload = function() { 
     console.log("Image " + i + ", " + j + " loaded"); 
    }; 
})(i); 

Cela démontre la différence entre i, qui est une variable de boucle et les changements, et j, qui est un paramètre lié à la fonction, qui ne change pas.

Voir la jsFiddle ici: