Comprendre le problème

Parent Previous Next



Comprendre le problème



Les closures n'existent pas simplement pour décorer, il existe des raisons bien particulières pour lesquelles elles ont été conçues. Les problèmes qu'elles sont supposées résoudre ne sont pas simples à comprendre, nous allons tâcher de vous expliquer cela au mieux.


Premier exemple


Commençons par un exemple simple qui vous donnera un aperçu de l'ampleur du problème :

var number = 1;

 

setTimeout(function() {

    alert(number);

}, 100);

 

number++;


Si vous avez essayé le code, alors vous avez sûrement remarqué le problème : la fonction alert() ne nous affiche pas la valeur 1 comme nous pourrions le penser, mais la valeur 2. Nous avons pourtant fait appel à setTimeout() avant le changement de valeur, alors comment se fait-il qu'il y ait ce problème ?


Eh bien, cela vient du fait que ce n'est que la fonction setTimeout() qui a été exécutée avant le changement de valeur. La fonction anonyme, elle, n'est exécutée que 100 millisecondes après l'exécution de setTimeout(), ce qui a largement laissé le temps à la valeur de number de changer.


Si cela vous semble étrange, c’est probablement parce que vous partez du principe que, lorsque nous déclarons notre fonction anonyme, celle-ci va directement récupérer les valeurs des variables utilisées. Que nenni ! Lorsque vous déclarez votre fonction en écrivant le nom d'une variable, vous passez une référence vers cette variable à votre fonction. Cette référence sera ensuite utilisée pour connaître la valeur de la variable, mais seulement une fois la fonction exécutée !


Maintenant que le problème est probablement plus clair dans votre tête, passons à un exemple plus concret !


Un cas concret


Admettons que vous souhaitiez faire apparaître une dizaine de balises <div> de manière progressive, les unes à la suite des autres. Voici le code que vous tenteriez probablement de faire dans l'état actuel de vos connaissances :

var divs = document.getElementsByTagName('div'),

    divsLen = divs.length;

 

for (var i = 0 ; i < divsLen ; i++) {

 

    setTimeout(function() {

        divs[i].style.display = 'block';

    }, 200 * i); // Le temps augmentera de 200 ms à chaque élément

 

}


Alors ? Le résultat n'est pas très concluant, n'est-ce pas ? Si vous jetez un coup d’œil à la console d'erreurs, vous constaterez qu'elle vous signale que la variable divs[i] est indéfinie, et ce dix fois de suite, ce qui correspond à nos dix itérations de boucle. Si nous regardons d'un peu plus près le problème, nous constatons alors que la variable i vaut toujours 10 à chaque fois qu'elle est utilisée dans les fonctions anonymes, ce qui correspond à sa valeur finale une fois que la boucle a terminé son exécution.


Ceci nous ramène au même problème : notre fonction anonyme ne prend en compte que la valeur finale de notre variable. Heureusement, il existe les closures, qui peuvent contourner ce désagrément !


Créé avec HelpNDoc Personal Edition: Générateur de documentations PDF gratuit

Site à deux balles