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.
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 !
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