Ergebnis 1 bis 9 von 9
  1. #1
    BurninLeo ist offline Grünschnabel
    registriert
    05-06-2007
    Beiträge
    8

    Unhappy Geltungsbereich - Argumente von Funktionen in Funktionen

    Hallo,

    ich habe ein schwerwiegendes Problemchen, das mich inzwischen mehrere Stunden beschäftigt hat: Ich möchte einem Button dynamisch ein onclick-Event zuweisen. Das Problem dabei ist, dass ich beim Zuweisen auch einen Wert für die onclick-Funktion mitgeben möchte. Am liebsten so:

    HTML-Code:
    // Soweit klappt es
    funktion kopieren() {
        var $v = "Test";
        button.onclick =  function() { funktionXY($v); }
    }
    Obwohl die Variable $v eigentlich gar nicht mehr existiert, wenn das onclick-Event ausgelöst wird (sie steht ja im Scope der übergeordneten Funktion), kann auf den Wert noch zugegriffen werden. Das ist fein - klappt aber nur so lange, wie ich den Wert in der Funktion nicht ändere. Folgendes klappt schon nicht mehr:


    HTML-Code:
    // weist beiden Events das gleiche Attribute zu
    funktion kopieren() {
        var $v = "Test";
        button1.onclick =  function() { funktionXY($v); }
        $v = "Anderes";
        button2.onclick =  function() { funktionXY($v); }
    }
    Natürlich könnte ich Variable einfach anders benennen - aber ich will das Ganze in einer Schleife machen. Und ich könnte die Funktion auch per new Function aufrufen - aber ich muss zusätzlich noch ein Objekt übergeben (vereinfaches Problem s. Beispiel unten).

    HTML-Code:
    // Kann kein Objekt aus der Funktion übergeben
    button1.onclick = new Function('funktionXY('+$v+')');

    Die einzige Lösung die mir nun einfällt ist, dem Button(-Objekt) ein zusätzliches Attribut zu verpassen, in dem ich den Wert zwischenspeichere. Das erscheint mir aber nicht besonders sauber, da es ja schon eine Reihe vorbelegter Attribute (z.B. onclick) gibt. Und natürlich ist es nicht besonders hübsch, in definierten Objekte einfach mit neuen Attributen herumzupfuschen.

    HTML-Code:
    // nicht so - ähm - objektorientiert
    funktion kopieren() {
        var $v = "Test";
        button1.onclick =  function() { funktionXY(); }
        button1.meinWert = $v;
        $v = "Anderes";
        button2.onclick =  function() { funktionXY(); }
        button2.meinWert = $v;
    }
    Meine 2 Fragen:

    1. Wer kann mir den Geltungsbereich der Variablen in Funktionen für untergeordnete Funktionen erklären? Wenn ich this verwende, greift das offenbar auf den Button zu (nicht wie evtl. zu erwarten auf die Funktion), das $v bezieht sich aber auf die lokale Variable.

    2. Gibt es eine elegantere Lösung, als die Variable im Button-Objekt zu hinterlegen? Wer weiß, ob künftige Browser-Generationen da keine Sicherheitsprobleme sehen und das blocken...


    Hier etwas Code, der das Problem demonstriert. Das Objekt, das ich zusätzlich übergeben muss ist hier das übergeordnete Menü (im echten Problem ein anderes Objekt). Den Fehler sieht man, wenn man mehrfach auf "Buttons kopieren" klickt und dann auf einige Buttons.

    HTML-Code:
    <html>
    <head>
    <title>Test für Geltungsbereiche</title>
    </head>
    <body>
    <h1>Test für Geltungsbereiche in JS</h1>
    <h2>Original Buttons</h2>
    <div id="menu">
    	<button class="aktion1">B1</button>
    	<button class="aktion2">B2</button>
    	<button class="aktion3">B3</button>
    </div>
    <p><button onclick="kopiereButtons()">Buttons kopieren</button></p>
    
    <div id="insert">
    <h2>Neue Buttons</h2>
    </div>
    
    <script type="text/javascript">
    <!--
    function kopiereButtons() {
    	var $menu = document.getElementById('menu');
    	var $neu = $menu.cloneNode(true);
    	$neu.removeAttribute('id');
    	var $buttons = $neu.getElementsByTagName('button');
    	for (var $i=0; $i<$buttons.length; $i++) {
    		// Zur Kontrolle
    		$buttons[$i].innerHTML = "Nummer " + $i;
    		// Alternative Lösung
    		$buttons[$i].myNum = $i;
    		// Hier die Problem-Stelle
    		$buttons[$i].onclick = function() { reaction(this, $neu, $i); }
    	}
    	var $insert = document.getElementById('insert');
    	$insert.appendChild($neu);
    }
    function reaction($this, $menu, $content) {
    	$this.style.border = '2px solid #0090FF';
    	$menu.style.backgroundColor = '#EFEFEF';
    	alert("Falsch: " + $content + " - Richtig wäre: " + $this.myNum);
    }
    // -->
    </script>
    </body>
    </html>
    Ja. Ich programmiere üblicherweise PHP - deshalb schreibe ich auch in JS gerne $ vor die Variablen. Danke schonmal im Voraus für alle Tipps!

  2. #2
    ein schlauer ist offline Lounge-Member
    registriert
    18-08-2004
    Beiträge
    14.671

    AW: Geltungsbereich - Argumente von Funktionen in Funktionen

    Das ist mal ein Beispielhaftes Posting wie man ein Problem erklärt und dabei zeigt das man selber mitdenkt, das muss mal gesagt werden da das leider nicht selbstverständlich ist.

    zu deinem Problem, du hast eigentlich schon alle Lösungsmöglichkeiten genannt und auch deine Analysen sind richtig. Ich bevorzuge die Möglichkeit dem Objekt zusätzliche attribute zu geben, es sollte nicht zu oft vorkommen.

  3. #3
    ToM80 ist offline Foren-Gott
    registriert
    27-03-2006
    Ort
    Neuss
    Beiträge
    2.729

    AW: Geltungsbereich - Argumente von Funktionen in Funktionen

    Mal eine Zwischenfrage als Größtenteils JavaScript Laie.
    Aber Variablen im Javascript haben doch kein "$" voran oder geht das auch??
    Meines Wissens sind das PHP-Variablen.

    Grüße

    ToM80

  4. #4
    cybaer ist offline Kaiser
    registriert
    12-09-2006
    Beiträge
    1.338

    AW: Geltungsbereich - Argumente von Funktionen in Funktionen

    Zitat Zitat von BurninLeo Beitrag anzeigen
    Das erscheint mir aber nicht besonders sauber, da es ja schon eine Reihe vorbelegter Attribute (z.B. onclick) gibt. Und natürlich ist es nicht besonders hübsch, in definierten Objekte einfach mit neuen Attributen herumzupfuschen.
    Das ist sehr hübsch! U.a. dafür ist die Objektorientiertheit auch da.

    Zitat Zitat von ToM80 Beitrag anzeigen
    Aber Variablen im Javascript haben doch kein "$" voran oder geht das auch??
    Ja, ja.

    Das "$" ist überflüssig, aber seit JS 1.1 allgemein erlaubt.
    Gruß, Cybaer

  5. #5
    BurninLeo ist offline Grünschnabel
    registriert
    05-06-2007
    Beiträge
    8

    AW: Geltungsbereich - Argumente von Funktionen in Funktionen

    Zitat Zitat von cybaer Beitrag anzeigen
    Das ist sehr hübsch! U.a. dafür ist die Objektorientiertheit auch da.
    Danke erstmal für die Antworten. Das beruhigt mich schonmal
    (Obwohl sich Java wohl beschweren würde, wenn ich da an ein Objekt zur Laufzeit noch Variablen dranhängen wollte... oder?)

    Ich bin noch über eine Kleinigkeit gestolpert, die ich zunächst übersehen hatte. Eine Funktion in der Funktion wird in JavaScript ja (auch) als Methode eines Objekts interpretiert. Das erklärt aber leider immer noch nicht den seltsamen Geltungsbereich. Für die eingeschlossenen Funktionen sind die Variablen der übergeordneten Funktion nämlich nicht "wie" globale oder objekteigene Variablen...


    Vielleicht könnt ihr noch meine vorerst letzte Frage beantworten: Warum "versteht" die aufgerufene Funktion das "this" aus der Perspektive des Buttons, das $neu und $i aber aus der Perspektive der übergeordneten Funktion. Ich meine diese Zeilen:

    HTML-Code:
    $buttons[$i].onclick = function() { reaction(this, $neu, $i); }
    und

    HTML-Code:
    function reaction($mythis, $menu, $content) {
    	$mythis.style.border = '2px solid #0090FF';
    	$menu.style.backgroundColor = '#EFEFEF';
    	alert("Falsch: " + $content + " - Richtig wäre: " + $mythis.myNum);
    }
    $mythis erhält eine Referenz zum neuen Button. Dort wo das this zugewiesen wird, dort wo auch $neu und $i gültig sind, müsste this aber eigentlich auf den Button "Buttons kopieren" zeigen... Geheimnis von JavaScript???

  6. #6
    ein schlauer ist offline Lounge-Member
    registriert
    18-08-2004
    Beiträge
    14.671

    AW: Geltungsbereich - Argumente von Funktionen in Funktionen

    this bezieht sich immer auf den Kontext, hier aus dem heraus die Funktion aufgerufen wird.

    $buttons[$i].onclick = function() { /* hier ist this == $buttons[i] */}

    Die lokalen Variabeln sind sowas wie private Variabeln auf die jede Funktion innerhalb deiner Funktion zugreifen kann zu jedem Zeitpunkt, daher werden bei dem Klick die aktuellen Werte, d.h. die zum Zeitpunkt des Klicks aktuellen Werte, von $i und $neu übergeben.

  7. #7
    Avatar von Albu
    Albu ist offline Foren-Gott
    registriert
    04-07-2001
    Beiträge
    13.501

    AW: Geltungsbereich - Argumente von Funktionen in Funktionen

    this ist ein reservierter Bezeichner in Javascript und steht immer für das zum Auswertezeitpunkt aktive Objekt. Bei $mythis dagegen wird this früher ausgewertet und eine Referenz auf ein konkretes this gebildet, welche dann übergeben wird. Das Feature lokale Variablen einer eingebetteten anonymen Funktion übergeben und sie dort auch über die Laufzeit der lokalen Funktion hinaus nutzen zu können, kann man für viele Nettigkeiten genutzt werden und macht viele Anwendungsfälle überhaupt erst möglich.

    Eine kleine Anmerkung zu $-Variablen: Solltest Du irgendwann einmal ein Framework ala mootools oder PrototypeJS einsetzen wollen, dann dürftest Du mit Namenskonflikten zu kämpfen haben, denn diese Frameworks verwenden $ Funktionen für zentrale Aufgaben. Deswegen wäre ich da ein wenig vorsichtig.
    1. Get people to play Space Taxi
    2. Sell real estates on neptun
    3. Profit!

    IE is not a browser, it is a scream.


    Outside of a dog, a book is man's best friend. Inside of a dog, it's too dark to read.

  8. #8
    ein schlauer ist offline Lounge-Member
    registriert
    18-08-2004
    Beiträge
    14.671

    AW: Geltungsbereich - Argumente von Funktionen in Funktionen

    sieht in JS auch irgendwie blöd aus

  9. #9
    cybaer ist offline Kaiser
    registriert
    12-09-2006
    Beiträge
    1.338

    AW: Geltungsbereich - Argumente von Funktionen in Funktionen

    Zitat Zitat von BurninLeo Beitrag anzeigen
    (Obwohl sich Java wohl beschweren würde, wenn ich da an ein Objekt zur Laufzeit noch Variablen dranhängen wollte... oder?)
    Warum sollte sich eine (echte) objektorientierte Sprache (nicht so'n aufoktroyiertes Gesummse wie bei PHP) beschweren, wenn man objektorientiert arbeitet?

    Ne, ne ...

    Eine Funktion in der Funktion wird in JavaScript ja (auch) als Methode eines Objekts interpretiert.
    Sie ist die Methode eines Objekts - Du nennst es halt "Funktion".

    Und auch "normale" Funktionen sind Methoden eines Objekts; nämlich des window-Objekts. Und globale Variablen sind Eigenschaften des window-Objects.

    Für die eingeschlossenen Funktionen sind die Variablen der übergeordneten Funktion nämlich nicht "wie" globale oder objekteigene Variablen...
    Warum lokale Variablen nun nicht auch Eigenschaften ihres Funktionsobjekts sind, würde mich auch mal interessieren. Ich habe darauf keine Antwort und finde es auch unlogisch. Insofern arbeite ich ggf. dann auch hier lieber mit Eigenschaften als mit lokalen Variablen.

    Oft ist es aber auch praktischer, wenn man weder globale noch lokale Variablen noch Funktionseigenschaften verwendet, sondern einem HTML-Element neue Eigenschaften zuweist! Z.B. bei Fadern die mehrfach parallel arbeiten müssen, weise ich die temporären/variablen Werte deswegen dem jeweiligen HTML-Element als Eigenschaft zu, für das der Fader wirken soll.
    Gruß, Cybaer

Ähnliche Themen

  1. Brauche dringend Tipps zum Umgang mit Funktionen in PHP
    Von evergreen im Forum Serverseitige Programmierung
    Antworten: 8
    Letzter Beitrag: 09-06-2006, 15:41
  2. Antworten: 0
    Letzter Beitrag: 28-02-2006, 09:47
  3. Antworten: 15
    Letzter Beitrag: 12-11-2005, 01:22
  4. Antworten: 17
    Letzter Beitrag: 24-01-2004, 15:37
  5. 2 Funktionen auf einem Event?
    Von simcen im Forum JavaScript
    Antworten: 1
    Letzter Beitrag: 31-10-2001, 12:15

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •