[JavaScript] problème de "closure" (résolut)

problème de "closure" (résolut) [JavaScript] - HTML/CSS - Programmation

Marsh Posté le 21-04-2009 à 11:56:06    

Bonjour à tous,
 
j'ai un petit souci avec le passage de variable utilisé au sein d'une fonction: Du fait du "closure" (je ne connais pas le terme Français), je n'obtiens pas la variable escompté.  
 
Je vais donner un exemple simplifié:
 
Imaginons les structures suivantes:

Code :
  1. var actions = {
  2.    'UP': 1,
  3.    'DOWN': 2,
  4.    'LEFT': 3,
  5.    'RIGHT': 4
  6. };
  7.  
  8. var buttons = ['UP', 'DOWN', 'LEFT', 'RIGHT'];


Si je procède ainsi:

Code :
  1. for (var b in buttons) {
  2.    var index = actions[buttons[b]];
  3.    bindKey(buttons[b], function () { // bindKey() est une fonction que j'ai créer qui me permet d'associer à une touche un callback...
  4.        alert(index);
  5.    });
  6. }


Quand j'appuie sur les touches UP, DOWN, LEFT et RIGHT, alert(index) m'affiche toujours undefined car index c'est fait modifier entre temps (sorte de variable global dû au "closure"...)
 
Par contre, si je procède ainsi:

Code :
  1. function bindKey2(button, index){
  2.    bindKey(button, function () {
  3.        alert(index);
  4.    });
  5. }
  6.  
  7. for (var b in buttons) {
  8.    var index = actions[buttons[b]];
  9.    bindKey2(buttons[b], index);
  10. }

Dans ce cas, alert(index) m'affiche bien 1, 2, 3, 4 et non undefined. Ceci est du au fait que en appelant la fonction bindKey2, les variables passé en paramètre sont des instances de ces variable et non des références aux variables global.
 
Ma question est la suivante: Comment écrire ceci sans passer par une fonction intermédiaire (bindKey2 dans mon exemple)?


Message édité par ZeBorG le 23-04-2009 à 01:11:54
Reply

Marsh Posté le 21-04-2009 à 11:56:06   

Reply

Marsh Posté le 22-04-2009 à 22:48:49    

si c était juste un problème de closure t aurais pas 4 fois "4" plutot ?
je pense plutot que comme ta callback se lance sur un event ca décale ton scope
t as essayé de déclarer index au meme niveau que bindKey ?


---------------
« The enemy is the gramophone mind, whether or not one agrees with the record that is being played at the moment. » — George Orwell
Reply

Marsh Posté le 22-04-2009 à 23:04:47    

à tester

 
Code :
  1. for (var b in buttons)
  2. {
  3.    var index = actions[buttons[b]];
  4.    bindKey.call (buttons[b], buttons[b], function () { alert (this) });
  5. }
 

[:_edit]
Ca marche pas :o
Tu as le code de ton bindKey ?


Message édité par SICKofitALL le 22-04-2009 à 23:18:20

---------------
We deserve everything that's coming...
Reply

Marsh Posté le 23-04-2009 à 00:04:07    

Bon ca marche comme ca avec une vrai closure :

Code :
  1. for (var b in buttons)
  2. {
  3.    var index = actions[buttons[b]];
  4.    bindKey (buttons[b], (function () { var cIndex = index; return function () { alert (cIndex) } } ) () );
  5. }
 

cIndex devient une sorte de variable statique et c'est elle qu'on affiche plutot qu'index, qui a évolué entre l'instanciation de la fonction et son affichage.

 

[:_edit]
version plus lisible

Code :
  1. var f = function () { var cIndex = index; return function () { alert (cIndex) } };
  2. for (var b in buttons)
  3.   {
  4.     var index = actions[buttons[b]];
  5.     bindKey (buttons[b], f () );
  6.   }



Message édité par SICKofitALL le 23-04-2009 à 00:07:33

---------------
We deserve everything that's coming...
Reply

Marsh Posté le 23-04-2009 à 00:36:20    

Je me disais bien que la réponse allait être évidente. Suffisait d'y penser ;)
 
Merci bien :)

Reply

Marsh Posté le 23-04-2009 à 00:40:15    

De rien :)
Ca m'a permis de me rendre compte que je passais souvent bcp de temps à gérer le scope à coups de call et apply, alors que dans la majorité des cas, une bonne closure fait l'affaire :o


---------------
We deserve everything that's coming...
Reply

Marsh Posté le 23-04-2009 à 01:06:13    

Pour que ce soit un peu plus claire dans ma tête j'ai externalisé la closure de la manière suivante:

Code :
  1. for (var b in buttons) {
  2.    (function () { // we create a closure in order to keep the current value of index at the time of the loop iteration
  3.        var index = actions[buttons[b]];
  4.        bindKey(buttons[b], function () {
  5.            alert(index);
  6.        });
  7.    })();
  8. }

Merci encore :)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed