Javascript multiples dynamique addEventListener créé en de la boucle - passant des paramètres ne fonctionne pas
Je veux utiliser des écouteurs d'événement pour empêcher la remontée d'événements sur une div dans une div avec onclick fonctions. Cela fonctionne, en passant des paramètres de la façon dont j'ai prévu:
<div onclick="doMouseClick(0, 'Dog', 'Cat');" id="button_id_0"></div>
<div onclick="doMouseClick(1, 'Dog', 'Cat');" id="button_id_1"></div>
<div onclick="doMouseClick(2, 'Dog', 'Cat');" id="button_id_2"></div>
<script>
function doMouseClick(peram1, peram2, peram3){
alert("doMouseClick() called AND peram1 = "+peram1+" AND peram2 = "+peram2+" AND peram3 = "+peram3);
}
</script>
Cependant, j'ai essayé de créer plusieurs écouteurs d'événement dans une boucle avec ceci:
<div id="button_id_0"></div>
<div id="button_id_1"></div>
<div id="button_id_2"></div>
<script>
function doMouseClick(peram1, peram2, peram3){
alert("doMouseClick() called AND peram1 = "+peram1+" AND peram2 = "+peram2+" AND peram3 = "+peram3);
}
var names = ['button_id_0', 'button_id_1', 'button_id_2'];
for (var i=0; i<names.length; i++){
document.getElementById(names[i]).addEventListener("click", function(){
doMouseClick(i, "Dog", "Cat");
},false);
}
</script>
Correctement attribue la fonction de clic à chaque div, mais le premier paramètre pour chaque, peram1
, est 3
. Je m'attendais à 3 différents gestionnaires d'événements de toutes de passage les différentes valeurs de i
pour peram1
.
Pourquoi est-ce arrivé? Sont les gestionnaires d'événement sont pas tous distincts?
Vous devez vous connecter pour publier un commentaire.
Problème, c'est les fermetures, car le JS n'a pas de bloc de portée (uniquement portée de la fonction)
i
n'est pas ce que vous en pensez parce que la fonction d'événement crée une autre portée donc, le temps que vous utilisezi
c'est déjà la dernière valeur de lafor
boucle. Vous avez besoin de garder la valeur dei
.À l'aide d'une IIFE:
À l'aide de
forEach
:i
était à tomber hors de la portée et au retour d'uneundefined
élément.Comme le soulignait déjà le problème est de le faire avec des bouchons et de la portée des variables. Une façon de s'assurer de la juste valeur est adoptée consiste à écrire une fonction qui renvoie à la fonction souhaitée, tenant les variables au sein de la droite portée. jsfiddle
Et d'illustrer une façon pour vous de le faire avec un objet à la place:
ou légèrement différemment:
Tout est global en javascript. C'est l'appel de la variable
i
qui est fixé à 3 après votre boucle...si vous définissezi
à 1000 après la boucle, puis, à chaque appel de la méthode produire 1000 pouri
.Si vous souhaitez conserver l'état, alors vous devriez utiliser des objets. Avoir l'objet ont une méthode de rappel que vous attribuez à la méthode de clic.
Vous avez mentionné le faire pour de remontée d'événements...pour l'arrêt de l'événement bublling, vous n'avez vraiment pas besoin de cela, car il est intégré dans la langue. Si vous ne voulez empêcher la remontée d'événements, alors vous devriez utiliser le
stopPropagation()
méthode de laevent
objet passé à la fonction de rappel.C'est à cause des fermetures.
Check this out: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Creating_closures_in_loops_A_common_mistake
L'exemple de code et votre code est essentiellement le même, c'est une erreur commune pour ceux qui ne savent pas "fermeture".
Pour faire simple, lors de votre créer une fonction de gestionnaire, il n'est pas seulement accède à la variable
i
de l'environnement extérieur, mais aussi "se souvient"i
.Ainsi, lorsque le gestionnaire est appelé, il va utiliser la
i
mais la variablei
est maintenant, après la boucle for, 2.