2010-09-05 8 views
1

Possible en double:
Javascript closure inside loops - simple practical exampleJavaScript: Pouvez-vous substituer des variables dans des fonctions anonymes sur la création?

Plutôt que d'expliquer la question, je vais vous donner un exemple:

for (var i = 0; i < 100; i ++) { 
    get_node(i).onclick = function() { 
    do_something_very_important(i); 
    } 
} 

Est-il possible d'avoir la valeur de i substitué dans la fonction lors de la création plutôt que de l'exécution? Merci.

+2

en double de http://stackoverflow.com/questions/750486 –

+0

cela ne fait pas de sens pour moi. "Lors de la création" me fait penser que vous voulez une variable statique. Votre exemple utilise i, où il fait partie de la structure de contrôle de boucle. Si les fermetures sont ce que vous voulez, c'est complètement différent. – vol7ron

+0

Pour beaucoup plus d'incarnations de la même question/problème, voir la section "Linked" dans le duplicata lié par Ian. – sth

Répondre

1

Oui, vous pouvez, mais cela ne fonctionnera pas pour l'exemple que vous avez fourni. Vous auriez a very common closure problem dans cette boucle for.

variables enfermées dans une fermeture partagent le même environnement unique, donc au moment où le rappel onclick est appelée, la boucle for aura suivi son cours, et la variable i sera pointera à la dernière valeur, il a été affecté. Dans votre exemple, la fonction do_something_very_important() recevra la valeur 100 pour chaque nœud, ce qui n'est pas ce que vous souhaitez.

Vous pouvez résoudre ce problème avec encore plus de fermetures, en utilisant une usine de fonction:

function makeClickHandler(i) { 
    return function() { 
    do_something_very_important(i); 
    }; 
} 

// ... 

for(var i = 0; i < 100; i++) { 
    get_node(i).onclick = makeClickHandler(i); 
} 

Cela peut être un sujet très délicat, si vous n'êtes pas familier avec le fonctionnement des fermetures. Vous pouvez consulter l'article Mozilla suivant pour une brève introduction:


MISE À JOUR:

Vous pouvez également inline l'usine de fonction ci-dessus @adamse suggested in the other answer. Ceci est en fait une approche plus commune, mais est pratiquement le même que ci-dessus:

for(var i = 0; i < 100; i++) { 
    get_node(i).onclick = (function(p) { 
    return function() { 
     // we could have used i as a parameter variable as well, 
     // but we're using p to better illustrate what's happening 
     do_something_very_important(p); 
    } 
    })(i); 
} 

Toute autre solution consiste à enfermer chaque itération dans sa propre portée, en utilisant l'auto invoquant des fonctions anonymes:

for(var i = 0; i < 100; i++) { 
    (function (p) { 
    // we now have a separate closure environment for each 
    // iteration of the loop 
    get_node(i).onclick = function() { 
     do_something_very_important(p); 
    } 
    })(i); 
} 
+0

Merci pour le lien, qui a été utile. – Jesse

0

Oui cela fonctionne ...

for (var i = 0; i < 100; i++) { 
    get_node(i).onclick = (function(i) { 
    return function() { 
     do_something_very_important(i); 
    } 
    })(i); 
} 
+0

Merci, c'est exactement ce que je cherchais. – Jesse

Questions connexes