En programmation, les fermetures jouent un rôle crucial dans la capture des variables des portées externes. Cependant, lorsqu’ils sont utilisés dans des boucles, ils peuvent conduire à des résultats inattendus appelés pollution de fermeture. Cet article explore ce problème et propose des solutions pratiques pour le résoudre.
Considérez le code suivant :
<code class="javascript">var funcs = []; for (var i = 0; i < 3; i++) { funcs[i] = function() { console.log("My value:", i); }; } for (var j = 0; j < 3; j++) { funcs[j](); }</code>
Malheureusement, ce code renvoie :
<code>My value: 3 My value: 3 My value: 3</code>
plutôt que :
<code>My value: 0 My value: 1 My value: 2</code>
Le problème se pose car chaque fonction déclarée dans la boucle capture la même i
variable de la portée externe. Lorsque les fonctions sont invoquées dans la deuxième boucle, elles font toutes référence au même i
, qui a été incrémenté à 3 au moment de leur exécution.
let
ES6 a introduit le mot-clé let
, qui crée des variables de portée bloc. L'utilisation de let
dans la boucle garantit que chaque itération a sa propre variable i
distincte, résolvant ainsi le problème de pollution de fermeture :
<code class="javascript">for (let i = 0; i < 3; i++) { funcs[i] = function() { console.log("My value:", i); }; }</code>
forEach
Une autre La solution pour les tableaux est d'utiliser la méthode forEach
:
<code class="javascript">var someArray = [/* values */]; someArray.forEach(function(element) { // ...code specific to this element... });</code>
Chaque itération de la boucle forEach
crée sa propre fermeture, capturant l'élément du tableau spécifique à cette itération.
La solution classique consiste à lier manuellement la variable à une valeur distincte et immuable en dehors de la fonction :
<code class="javascript">var funcs = []; function createFunc(i) { return function() { console.log("My value:", i); }; } for (var i = 0; i < 3; i++) { funcs[i] = createFunc(i); } for (var j = 0; j < 3; j++) { funcs[j](); }</code>
En passant la variable i
comme argument à l'intérieur fonction, nous créons une nouvelle fermeture pour chaque itération, en veillant à ce que chaque fonction fasse référence à sa propre valeur indépendante.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!