Manuel_guest: JS-Variable in onclick-Ereignis einfügen?

Hallo :)

Ich wüsste gerne, wie ich folgendes Szenario in JS richtig löse:

  
function foobar()  
{  
  for(var i=1; i <= 5; i++)  
  {  
    var x = document.createElement("input");  
    x.type="button";  
    x.value = i;  
    x.onclick = function(){alert(i);} // should alert 1 .. 5 !  
    document.body.appendChild(x);  
  }  
}  

Die generierten Button's sollen den Wert von 'i' ausgeben, den i zum Zeitpunkt der Zuweisung des onClick-Events hat.
Alternativ könnte ich es hier lösen, indem ich

x.onclick = function(){alert(this.value);}

machen würde, dies ist aber natürlich nicht immer möglich :)

Wo mache ich etwas falschund wie macht man es richtig?

Danke :)

  1. Hi,

    function foobar()
    {
      for(var i=1; i <= 5; i++)
      {
        var x = document.createElement("input");
        x.type="button";
        x.value = i;
        x.onclick = function(){alert(i);} // should alert 1 .. 5 !
        document.body.appendChild(x);
      }
    }

    x.i = i;
    x.onclick = function(){alert(this.i);}

    Gruesse, Joachim

    --
    Am Ende wird alles gut.
    1. Hi,

      x.i = i;
      x.onclick = function(){alert(this.i);}

      Das ist eine Möglichkeit, Closures wären eine weitere.

      MfG ChrisB

      --
      “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
      1. Hallo,

        Hi,

        x.i = i;
        x.onclick = function(){alert(this.i);}

        so habe ich das letztendlich auch gelöst, schien mir aber nur ein workaround zu sein :)
        Vielleicht der Vollständigheit wegen noch eine mir bekannte Möglichkeit:

        x.onclick = new Function( "alert("+i+")" );

        Allerdings versuche ich jenes immer zu vermeiden, aus Angst vor:
        i = '1);window.setInterval("alert(1)",10';

        Das ist eine Möglichkeit, Closures wären eine weitere.

        Hm, ich würde jetzt eher sagen, dass Closures mein Problem erst verursacht haben und sehe nicht, wie ich es darüber lösen könnte? Hättest Du lust die Idee auszuführen? :)

        Danke und Gruß,
        Manuel

        1. ich würde jetzt eher sagen, dass Closures mein Problem erst verursacht haben und sehe nicht, wie ich es darüber lösen könnte? Hättest Du lust die Idee auszuführen? :)

          indem du bei jedem schleifendurchlauf eine anonyme funktion erzeugst (per funktionsausdruck), diese direkt ausführst und dabei den schleifenzähler als parameter übergibst

          darin eine weitere closure notierst (die event-handler-funkton), die den schleifenzähler einschließt

          for (var i = 0; i < 5; i++) {
             (function (i) {
                ...
                element.onclick = function () {
                   alert("Das korrekte i:" + i);
                };
             })(i);
          }

          die closure sorgt dafür, dass das variablenobjekt der jeweiligen äußeren (anonymen, nicht gespeicherten, nur einmal ausgeführten) funktion erhalten bleibt. das liegt in der scope chain über dem variablenobjekt der event-handler-funktion, dort wird dann die variable i gefunden

          das ist aber ziemlich gefrickelt und nicht so performant (viele erzeugte funktionen und funktionsaufrufe, massig variablenobjekte, die im speicher verbleiben), es gibt einfachere und robustere methoden

          weiteres findet sich im archiv zu den stichwörtern closures und schleifen