50 votes

Passage de paramètres dans l'événement Javascript onClick

J'essaie de passer un paramètre dans l'événement onclick. Vous trouverez ci-dessous un exemple de code :

<div id="div"></div>

<script language="javascript" type="text/javascript">
   var div = document.getElementById('div');

   for (var i = 0; i < 10; i++) {
       var link = document.createElement('a');
       link.setAttribute('href', '#');
       link.innerHTML = i + '';
       link.onclick=  function() { onClickLink(i+'');};
       div.appendChild(link);
       div.appendChild(document.createElement('BR'));
       }

   function onClickLink(text) {
       alert('Link ' + text + ' clicked');
       return false;
       }
    </script>

Cependant, lorsque je clique sur l'un des liens, l'alerte indique toujours "Lien 10 cliqué" !

Quelqu'un peut-il me dire ce que je fais mal ?

Gracias

55voto

Jamie Wong Points 10858

Cela se produit parce que le i se propage vers le haut de la portée une fois que la fonction est invoquée. Vous pouvez éviter ce problème en utilisant une fermeture.

for (var i = 0; i < 10; i++) {
   var link = document.createElement('a');
   link.setAttribute('href', '#');
   link.innerHTML = i + '';
   link.onclick = (function() {
      var currentI = i;
      return function() { 
          onClickLink(currentI + '');
      }
   })();
   div.appendChild(link);
   div.appendChild(document.createElement('BR'));
}

Ou si vous voulez une syntaxe plus concise, je vous suggère d'utiliser la solution de Nick Craver.

0 votes

Superbe description de ce Jamie !

0 votes

Ha ! Parce que ce fermeture que nous définissons sur la droite de link.onclick = a accès à la fonction qui le contient, ce qui signifie que la fonction i à l'intérieur, il y a une référence à l'extérieur i et non une valeur copiée (comme dans le cas de l'option normale passe par valeur le passage des arguments) ! :)) Charmant. J'ai enfin compris :D

39voto

Nick Craver Points 313913

Cela se produit parce qu'ils font tous référence au même i qui change à chaque boucle, et laissée en tant que 10 à la fin de la boucle. Vous pouvez le résoudre en utilisant une fermeture comme celle-ci :

link.onclick = function(j) { return function() { onClickLink(j+''); }; }(i);

Vous pouvez l'essayer ici

Ou, faites this est le lien sur lequel vous avez cliqué dans ce gestionnaire, comme ceci :

link.onclick = function(j) { return function() { onClickLink.call(this, j); }; }(i);

Vous pouvez essayer cette version ici

1 votes

Juste pour être clair : vous renvoyez la déclaration d'une fonction anonyme qui accepte un paramètre j et au même moment vous passez le paramètre actuel aussi ? (le (i) )

3 votes

@dierre - Le (i) invoque le function(j) avec le paramètre étant l'actuel i ce qui l'amène à renvoyer la fonction dans laquelle une valeur copiée se trouve dans la fermeture, qui n'est plus connectée à la fonction i Est-ce que ça a un sens ?

0 votes

Il semble que c'est la même chose que ce que je dis mais je ne suis pas sûr : pour moi function(j) { return function() { onClickLink(j+'') ; } ; } est MaFonctionAnonyme(j) . Ce que je vois, c'est link.onclick = MaFonctionAnonyme(i) ;

3voto

Ryan Tenney Points 1485
link.onclick = function() { onClickLink(i+''); };

est une fermeture et stocke une référence à la variable i et non la valeur que i tient lorsque la fonction est créée. Une solution serait d'envelopper le contenu de la fonction for boucle dans une fonction faire ceci :

for (var i = 0; i < 10; i++) (function(i) {
    var link = document.createElement('a');
    link.setAttribute('href', '#');
    link.innerHTML = i + '';
    link.onclick=  function() { onClickLink(i+'');};
    div.appendChild(link);
    div.appendChild(document.createElement('BR'));
}(i));

0 votes

Je pense que vous avez quelques crochets mal équilibrés là. Cela devrait être })(i); sur la dernière ligne ?

1 votes

Cela fonctionne, tout comme l'omission des parenthèses extérieures, mais c'est le style "approuvé par Crockford" : stackoverflow.com/questions/939386/

1voto

Richard JP Le Guen Points 13306

Essayez ça :

<div id="div"></div>

<script language="javascript" type="text/javascript">
   var div = document.getElementById('div');

   for (var i = 0; i < 10; i++) {
       var f = function() {
           var link = document.createElement('a');
           var j = i; // this j is scoped to our anonymous function
                      // while i is scoped outside the anonymous function,
                      //  getting incremented by the for loop
           link.setAttribute('href', '#');
           link.innerHTML = j + '';
           link.onclick=  function() { onClickLink(j+'');};
           div.appendChild(link);
           div.appendChild(document.createElement('br')); // lower case BR, please!
       }(); // call the function immediately
   }

   function onClickLink(text) {
       alert('Link ' + text + ' clicked');
       return false;
   }
</script>

1voto

aniri Points 1279

Ou vous pouvez utiliser cette ligne :

 link.setAttribute('onClick', 'onClickLink('+i+')');

au lieu de celui-ci :

link.onclick=  function() { onClickLink(i+'');};

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X