2008-11-21 8 views
3

Ceci est vraiment une question de base, mais ...Comment utiliser la valeur d'une variable au moment de la déclaration dans une fonction anonyme JavaScript?

J'ai un code comme celui-ci

var arr = Array('blah.jpg','ha.jpg'); 
for (var i=0; i<array.length; i++) 
{ 
    $('div#blah' + i).click(function() { 
      $('img').attr('src', arr[i]); }); 
} 

Cela devrait lier la div avec id="blah0" changer toutes les images à 'blah.jpg' lorsque vous cliquez dessus. De même, en cliquant sur le div avec id ="blah1" devrait changer toutes les images à 'ha.jpg'. Cependant, la fonction anonyme ne fonctionnera pas car elle utilisera la valeur de 'i' au moment de l'exécution, c'est-à-dire 2. Cela signifie que cliquer sur div va essayer de régler toutes les images sur arr [2] - un élément inexistant (intéressant de ne pas lancer une erreur JS sur ma machine mais c'est une autre histoire ...).

Comment puis-je obtenir la fonction anonyme à l'aide de la valeur de 'i' au moment de la déclaration?

Comme un exemple plus simple:

for (var i=0; i<10; i++) 
{ 
    $('div#blah'+i).click(function() { 
     alert(i)); }); 
} 

Cela devrait afficher '0' quand je clique 'blah0', '1' quand je clique 'blah1' etc.

Cependant, par défaut, il afficher '10', peu importe lequel 'blah' je clique.

Répondre

5

Déclarez une nouvelle variable dans une fonction qui crée un nouveau gestionnaire de clic qui obtient la valeur actuelle de i en tant que paramètre:

function makeClickHandler(arr, local_i) { 
    return function() { 
     $('img').attr('src', arr[local_i]); 
    }; 
} 

var arr = Array('blah.jpg','ha.jpg'); 
for (var i=0; i<array.length; i++) 
{ 
    $('div#blah' + i).click(makeClickHandler(arr, i)); 
} 

Chaque instance de la fonction obtient sa propre copie de local_i, ça ne change pas à chaque fois.

+0

Je vais essayer maintenant - mais cela n'accèdera-t-il pas toujours à la valeur de chaque fois que je clique sur (i.e.définir local_i pour évaluer que 'i' est au moment du clic?) –

+0

Oui, c'est ce que je reçois. –

+0

Oups, je suppose que je n'ai pas assez prêté attention au contexte. –

0

Avoir 1 variable supplémentaire à l'intérieur de la boucle et l'incrémenter après l'avoir utilisée dans la fermeture.

 

var j = 0; 
for (var i=0; i<array.length; i++) 
{ 
    $('div#blah' + j).click(function() { 
      $('img').attr('src', arr[i]); }); 

    j++; 
} 
 
+0

Le problème n'est pas lié (c'est-à-dire 'div # blah' + j) mais l'accès au tableau (c'est-à-dire arr [i]). Dans la méthode que vous utilisez, il n'y aura pas de différence du tout - le clic appellera encore appelez le 'i'eme élément de arr en utilisant la valeur de i à ce moment (par exemple array.length) pas la valeur de i quand j'ai fait la fonction –

+0

Alors que je ne comprends pas beaucoup de fermeture, vous pouvez laisser le clic pour appeler une seule fonction et vérifier le Event.Src (qui vous donnera div1, div2 ou div3), en extraire l'identifiant et en fonction de cela définir la source d'image. – shahkalpesh

+0

Je n'ai pas essayé cela. Mais la nouvelle fonction() {...} est-elle possible? – shahkalpesh

0

J'ai cette réponse à ce jour, mais peu un hack:

var arr = Array('blah.jpg','ha.jpg'); 
for (var i=0; i<array.length; i++) 
{ 
    eval("$('div#blah' + i).click(function() { $('img').attr('src', arr[" + i + "]); })"); 
} 

aussi:

for (var i=0; i<10; i++) 
{ 
    eval("$('div#blah'+i).click(function() { alert(" + i + ")); });"); 
} 
+0

Pourrait également utiliser le piratage multiligne comme ici http://forums.whirlpool.net.au/forum-replies-archive.cfm/487804.html si trop long à ligne unique eval. –

4

Dans ce cas particulier, vous devriez utiliser une fermeture:

for (var i=0; i<10; i++) 
{ 
    (function(j){ 
     $('div#blah'+j).click(function() { alert(j)); }); 
    })(i);   
} 

(function(){ /* code */ })() indique une fonction auto-exécutable, ce qui implique qu'elle utilisera et évaluera la valeur de i immediat ely dans la boucle par opposition à au moment du clic.

+0

Ah chouette. Merci! –

Questions connexes