rookie: Übergabewert (lokale Variable) in anderer Funktion verwenden

Hallo allerseits!

Ich habe folgende Verständnisfrage:
Wie kann ich den Übergabewert einer Funktion (also eine lokale Variable) für eine andere Funktion verfügbar machen? Geht das mit Rückgabewerten und wenn ja wie?

  
function beispiel_1(e) {  
// Anweisungen (bspw. ist "e" ein String)  
}  
function beispiel_2() {  
// benötigt "e" zur Weiterverarbeitung (bspw. das Zusammensetzen einer URL)  
}  

Ich möchte globale Variablen vermeiden, um eine Kollission verschiedener Skripte zu verhindern, kann aber die beiden Funktionen nicht verschachteln.

Hoffe auf Hilfe :-)

Vielen Dank im Voraus
Ein Anfänger

  1. Hallo,

    Wie kann ich den Übergabewert einer Funktion (also eine lokale Variable) für eine andere Funktion verfügbar machen?

    1. Indem du die Werte als Parameter übergibst.

    function f1(e) {  
      f2(e);  
    }  
    function f2(e) {  
      alert(e);  
    }
    

    2. Indem du den Wert in einer Variablen in einem gemeinsamen übergeordneten Variablen-Scope speicherst.

    // Sofort ausgeführter Funktionsausdruck ([link:http://benalman.com/news/2010/11/immediately-invoked-function-expression/@title=IIFE])  
    (function() {  
      var gemeinsameVariable;  
      
      function f1(e) {  
        gemeinsameVariable = e;  
      }  
      function f2() {  
        alert(gemeinsameVariable);  
      }  
    })();
    

    Geht natürlich auch mit einer benannten Funktion.

    Grüße,
    Mathias

    1. Wunderbar!

      Habe mich für Variante zwei entschieden, da die zweite Funktion erst später aufgerufen werden soll.

      Vielen Dank!

      1. Tach!

        Habe mich für Variante zwei entschieden, da die zweite Funktion erst später aufgerufen werden soll.

        Vielleicht wäre dann Variante drei angemessener: f1() gibt das e über return zurück, du merkst dir das in einer Variable und übergibst es zur gegebenen Zeit an f2() als Parameter. Das entspräche auch eher den Prinzipien sauberer Programmierung. Man sieht bei einem Aufruf, dass die Funktion etwas haben will und was es ist, anstatt dass sie es einfach so irgendwo erwartet und es dort bereitstehen muss.

        dedlfix.

        1. Vielleicht wäre dann Variante drei angemessener: f1() gibt das e über return zurück, du merkst dir das in einer Variable und übergibst es zur gegebenen Zeit an f2() als Parameter. Das entspräche auch eher den Prinzipien sauberer Programmierung. Man sieht bei einem Aufruf, dass die Funktion etwas haben will und was es ist, anstatt dass sie es einfach so irgendwo erwartet und es dort bereitstehen muss.

          Das leuchtet natürlich ein.
          Würde mich interessieren, wie das umzusetzen ist.
          Hier mein ursprüngliches Beispiel:

            
          function beispiel_1(e) {  
          // Anweisungen (bspw. ist "e" ein String)  
          }  
          function beispiel_2() {  
          // benötigt "e" zur Weiterverarbeitung (bspw. das Zusammensetzen einer URL)  
          }  
          
          

          Gruß
          rookie

          1. Tach!

            Vielleicht wäre dann Variante drei angemessener: f1() gibt das e über return zurück, du merkst dir das in einer Variable und übergibst es zur gegebenen Zeit an f2() als Parameter.
            Würde mich interessieren, wie das umzusetzen ist.

            So wie man eben bei Funktionen einen Rückgabewert zurückgibt, ihn in Empfang nimmt und ganz allgemein einen Parameter übergibt. Das ist im Prinzip Grundlagenwissen.

              
            function beispiel_1(e) {  
            // Anweisungen (bspw. ist "e" ein String)  
              
              return e;  
            }  
              
            function beispiel_2(foo) {  
              
            // mach was mit foo  
            }  
              
            // Anwendung:  
              
            var x = beispiel_1(parameterwert);  
              
            beispiel_2(x);  
            
            

            Wenn x nicht global herumliegen soll, musst du eine Funtkion drumherumbauen, wie in molilys Variante 2.

            dedlfix.

            1. Grundlagenwissen ist eben das, was ich mir Schritt für Schritt zu erarbeiten suche.
              Danke!

            2. Eine Frage ergibt sich noch.
              Ich habe die Event-Handler samt und sonders in JavaScript definiert.
              Also etwas wie ...

                
              document.getElementById("id1").onclick = funktion1;  
              function funktion1() {funktion_allgemein("string1");}  
              document.getElementById("id2").onclick = funktion2;  
              function funktion2() {funktion_allgemein("string2");}  
              
              

              usw. -- ich habe auf diese Weise etwa 20 verschiedenen Links ebensoviele Funktionen zugewiesen.
              Die verschachtelten Funktionen benötige ich, um der inneren Funktion (die immer dieselbe ist) einen jeweils unterschiedlichen Übergabewert mitgeben zu könnnen.

                
              function funktion_allgemein(e) {  
              // arbeite mit "e"  
              }  
              
              

              In diesem Fall verstehe ich nicht, wie ich Deine Lösung umsetzen soll.

              rookie

              1. Hallo,

                document.getElementById("id1").onclick = funktion1;

                function funktion1() {funktion_allgemein("string1");}
                document.getElementById("id2").onclick = funktion2;
                function funktion2() {funktion_allgemein("string2");}

                
                >   
                > usw. -- ich habe auf diese Weise etwa 20 verschiedenen Links ebensoviele Funktionen zugewiesen.  
                  
                Das ist eine sehr komplexe Lösung, das ließe sich wahrscheinlich generalisieren und damit vereinfachen. Dann hast du das Probleme der Variablenübergabe gar nicht.  
                  
                
                > Die verschachtelten Funktionen benötige ich, um der inneren Funktion (die immer dieselbe ist) einen jeweils unterschiedlichen Übergabewert mitgeben zu könnnen.  
                  
                Das sieht so aus, als bräuchtest du weder 20 Event-Handler zu registrieren noch 20 Funktionen zu erzeugen. Das Schema wiederholt sich anscheinend gleichförmig. Gemäß der Regel »Don’t repeat yourself« sollte man diesen Code optimieren. Beispielsweise:  
                  
                - Gib allen fraglichen Elementen eine Klasse  
                - Überwache alle click-Ereignisse bei einem gemeinsamen Elternelement, z.B. body. Siehe [Event Delegation](http://molily.de/js/event-handling-effizient.html).  
                - Prüfe in diesem globalen Handler, ob das geklickte Element die Klasse besitzt. Wenn das nicht der Fall ist, breche ab.  
                - Der unterschiedlichen Übergabewert ergibt sich bestenfalls aus dem Kontext, z.B. entnimmst du ihn dem Element. Das kann wie oben im Beispiel die ID sein, ein [data-Attribut](http://html5doctor.com/html5-custom-data-attributes/), der Textinhalt, oder du suchst die benötigten Daten in einem dafür vorgesehenen JavaScript-Objekt.  
                  
                Es gibt noch einige andere Lösungsmöglichkeiten, die ich hier nicht genannt habe. Am besten zeigst du uns einmal ein Beispiel mit tatsächlichen Inhalten.  
                  
                Im Allgemeinen empfehle ich das [Kapitel Event-Handling meiner JavaScript-Dokumentation](http://molily.de/js/).  
                  
                Grüße,  
                Mathias
                
                1. Hallo!

                  Ha! Vielen Dank für diese Lektüre.
                  Ich werde mich eingehend damit beschäftigen!

                  Hier ein Link zum aktuellen Stand der Dinge (Ist ein reines Übungsprojekt):

                  Es geht um das Formular oben.
                  Im input "Was?" "Hotel" nehmen.
                  im input "Wohin?" "Phuket" wählen.

                  rookie

                  1. Da lag ich ja richtig mit meiner Vermutung. Du kannst hier einfach an drop1 bzw. drop2 einen Event-Handler registrieren, der alle Klicks auf die verschachtelten a-Elemente abfängt. Und die Art der Reise bzw. den Ortsnamen kannst du direkt dem a-Element entnehmen (innerHTML bzw. innerText/textContent). Den Dateinamen würde ich ins href-Attribut schreiben (die URL sollte auch erreichbar sein).

                    <ul class="drop2">  
                    <li><a href="bangkok.html">Bangkok</a></li>  
                    <!-- usw. -->  
                    </ul>
                    
                    document.getElementById('drop2').onclick = function(event) {  
                      event.preventDefault(); // [link:http://molily.de/js/event-handling-objekt.html#standardaktion@title=Standardaktion unterdrücken]  
                      var target = event.target || event.srcElement; // [link:http://molily.de/js/event-handling-objekt.html#currenttarget-target@title=Zielelement]  
                      if (target.nodeName !== 'A') return;  
                      var city = target.innerHTML;  
                      var url = target.href;  
                      wohin(city, url);  
                    };
                    

                    (ungetestet)

                    Damit werden IDs unnötig und du musst nicht jedem Element einen einzelnen Event-Handler zuweisen. Genauer wird das Vorgehen wie gesagt unter Effiziente Ereignisverarbeitung mit Event Delegation beschrieben.

                    Grüße,
                    Mathias

                    1. Hallo,

                      <ul class="drop2">
                      ______^
                      ...

                      </ul>

                      
                      >   
                      > document.getElementById('drop2').onclick = function(event) {  
                      
                      \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_^  
                      ...  
                      
                      >   
                      > (ungetestet)  
                      >   
                        
                      kann wohl nicht funktionieren.  
                        
                      Gruß  
                      Kalk
                      
                    2. Hallo Mathias!

                      Also erstmal vielen Dank für Deine Zeit.
                      Es ist ja nicht selbstverständlich, dass jemand sich hierfür einfach Zeit nimmt.

                      Für die erste Seite hat die Umsetzung wunderbar geklappt.
                      Bis auf das Unterdrücken der Standardaktion, die Folgeseite wird sofort aufgerufen (ohne den Button "Suchen" klicken zu müssen).

                      Für die zweite Seite ergeben sich seltsame Probleme:

                        
                      drop1.onclick = function(event) {  
                      	drop1.style.display = "none";//ausblenden des Dropdowns  
                      	var target = event.target || event.srcElement;  
                      	if(target.className == "strand") {  
                      		var beach = target.innerHTML;  
                      		var droplinks = drop1.getElementsByTagName("a");  
                      		for(i = 0; i < droplinks.length; i++) {  
                      			if(droplinks[i] == target) {  
                      				var hotelindex = i;  
                      			}  
                      		}  
                      	strand(hotelindex, beach);  
                      	}  
                      }  
                      
                      

                      ReferenceError: assignment to undeclared variable i (bezieht sich auf die Schleifenvariable -- input2.js -- Zeile 31)
                      Der IE8 meint, "target" sei null oder kein Objekt.
                      Vor allem musste ich die Links mit Klassennamen versehen, der nodeName wurde schlicht nicht erkannt.

                      Ich fürchte, heute ist nicht mein Tag :-)

                      Lieben Gruß
                      Bernhard

                      1. Hallo!

                        drop1.onclick = function(event) {
                        drop1.style.display = "none";//ausblenden des Dropdowns
                        var target = event.target || event.srcElement;

                        Da hatte ich im Beispielcode die Kompatibilität mit IE < 9 vergessen. In meiner Dokumentation wird das genauer erklärt.

                        Für IE < 9 fehlt hier diese erste Zeile:

                        if (!event) event = window.event;  
                        var target = event.target || event.srcElement;
                        

                        Dann müsste im IE < 9 der Zugriff auf event.srcElement gelingen, andere Browser kennen event.target.

                        Siehe Zugriff auf das Event-Objekt und Zielelement.

                          for(i = 0; i < droplinks.length; i++) {  
                        

                        Sieht eigentlich gut aus, es fehlt nur die Variablendeklaration mit »var«.

                        for (var i = 0; i < droplinks.length; i++) {}

                          	if(droplinks[i] == target) {  
                          		var hotelindex = i;  
                          	}  
                        

                        Du kannst die Schleife hier mit http://de.selfhtml.org/javascript/sprache/schleifen.htm#break_continue@title=break; abbrechen, sobald du den Treffer gefunden hast.

                        Viele Grüße,
                        Mathias

                        1. Sieht eigentlich gut aus, es fehlt nur die Variablendeklaration mit »var«.

                          Selbstverständlich. Manchmal sehe ich den Wald vor lauter Bäumen nicht mehr.

                          Ich verneige mich vor soviel Hilfsbereitschaft!

                          Lieben Gruß
                          Bernhard

        2. Hi!
          Im Grunde ist molilys Vorschlag nix anderes als ein globales Objekt zu erstellen und dort sowohl die Funktionen als auch die zu speichernden Werte vorzuhalten. Wenn man es uebersichtlicher haben will kann man das natuerlich explizit so machen und auch die Variable zugreifbar machen. Das letzte Beispiel im verlinkten Text beschreibt sowas. Da fehlte nur die zurueckgegebene Variable.

          man haette dan sowas wie
          myObj.variable
          myObj.f1()
          myObj.f2(myObj.variable)

          korrigiert mich, wenn ich mich irre.

          --
          Signaturen sind bloed.
          1. Hallo!

            Im Grunde ist molilys Vorschlag nix anderes als ein globales Objekt zu erstellen und dort sowohl die Funktionen als auch die zu speichernden Werte vorzuhalten.

            Ein lokaler Scope ist schon etwas anderes als ein globales Objekt. Ein Scope ist intern als ein Objekt umgesetzt, das stimmt.

            Ein einfaches Objekt zu erstellen und dort die Methoden und die Daten zu gruppieren ist ein guter Vorschlag. Dieses Objekt muss allerdings nicht global sein, sondern kann genauso in einem lokalen Scope leben.

            Grüße,
            Mathias