2010-05-21 6 views
1

j'ai cherché mais n'a pas pu trouver une réponse à cette question apparemment facile, donc ...question de la fonction Javascript

Supposons que j'ai une boucle dans laquelle je dois mettre callbacks. Ma fonction de rappel ressemble à ceci:

function callback(var1) { // code } 

Maintenant, ma boucle est quelque chose comme ceci:

for(//condition) 
{ 
    var x = something_different_each_time; 
    document.getElementById('foo').addEventListener('click', function() { callback(x); }, false); 
} 

Maintenant, il semble que même si les séries n fois la boucle, la fonction anonyme est compilé une seule fois - et donc toute invocation de rappel est appelée avec le même argument (même si x varie dans la boucle à chaque fois).

Je dois manquer quelque chose ici .. toute aide est grandement appréciée! :)

+1

Des questions similaires: http://stackoverflow.com/questions/1734749/ http://stackoverflow.com/questions/643542/ http://stackoverflow.com/questions/1582634/ http: //stackoverflow.com/questions/1331769/ http://stackoverflow.com/questions/1552941/ http://stackoverflow.com/questions/750486/ http://stackoverflow.com/questions/ 933343/ http://stackoverflow.com/questions/1579978/ http://stackoverflow.com/question s/1413916/ – CMS

+1

qui est une liste complète @CMS.Il serait bon de marquer ces questions avec des «fermetures» et des «boucles», de sorte qu'ils peuvent tous être liés à une simple recherche. – Anurag

+1

terminé, toutes les questions sont marquées "javascript", "fermetures" et "boucles". Voici le lien - http://stackoverflow.com/questions/tagged/javascript+closures+loops – Anurag

Répondre

2

Le problème est que le bloc de l'instruction for ne crée une nouvelle portée, pour cela, la variable x appartient à sa portée englobante, et toutes les fonctions anonymes se réfèrent à la même variable ...

Utilisez une autre fonction pour créer un nouvel environnement lexical pour maintenir la valeur de x à chaque itération:

for(/*condition*/) { 
    var x = something_different_each_time; 
    document.getElementById('foo').addEventListener('click', function() { 
    return function(y) { 
     callback(y); 
    }; 
    }(x), false); 
} 
+0

Je pense qu'il vous manque des accolades autour de votre expression de fonction anonyme. – deceze

+2

@deceze: Non, les parenthèses sont requises seulement quand la fonction est sur un endroit où elle peut provoquer une ambiguïté grammaticale entre une expression de fonction et une déclaration de fonction, dans ce cas, la fonction est dans la liste d'arguments d'un appel de fonction, c'est clairement sur le contexte d'expression, pas d'ambiguïté ... par exemple: '(function (fn) {fn();}) (function() {alert ('hi');});' – CMS

+0

@deceze: peut-être un meilleur exemple : 'var foo = fonction() {return 'barre'; }(); 'la fonction est invoquée sans problèmes ...' foo === 'bar'; ' – CMS

1

Vous devez calculer x avant d'appeler votre fonction de rappel!

for(//condition) 
{ 
    //var x = something_different_each_time; 
    document.getElementById('foo').addEventListener('click', function() { 
    var x = something_different_each_time; 
    callback(x); }, false); 
} 
+0

Ce n'est pas vraiment le problème. Merci quand même. – ragebiswas

0

Oui, la x se référera à la même variable dans la portée englobante, et puisque la fonction est l'exécution plus tard, ça aura la dernière valeur de x. Essayez ceci:

.addEventListener(
    'click', 
    (function (i) { 
     return function() { callback(i); } 
    })(x), 
    false 
); 

Cela crée une fermeture avec la valeur actuelle de x enfermé à l'intérieur.