Jul 2008

Funktionen als Parameter anderer Funktionen

 
 

Funktionen, die einen Rückgabewert liefern, können als Argumente von Funktionen verschachtelt werden. Funktionen in Javascript sind Objekte und können wie jeder andere Datentyp einer Variablen als Wert zugewiesen werden – wenn eine Funktion einen Integer-Wert zurückgibt, wird sie wie ein Integer behandelt.

Da Funktionen in JavaScript Objekte sind, sind sie Funktionen höherer Ordnung und können als Parameter an andere Funktionen übergeben werden. Da sie als Objekt behandelt werden, werden sie als Referenz übergeben und nicht als Wert (siehe auch call by reference und call by value).

function steuer( betrag, satz ) 
{
   return ( betrag + betrag * satz / 100 );
}

function checkNum( obj )
{
   if (isNaN( parseInt( obj.value ) )) {
      return 0;
   } else {
      return parseInt( obj.value );
   }
}

function nestFunc()
{
   var betrag = document.getElementById( 'betrag' );
   var mwstSatz = document.getElementById( 'mwstSatz' );
   var summe = steuer ( checkNum( betrag ), checkNum( mwstSatz ) );

   document.getElementById( 'summe' ).value = summe;
   return false;
}

Der Rückgabewert von checkNum() muss nicht in einer Variablen gespeichert werden, sondern wird direkt als Argument an den Aufruf der funktion steuer() eingesetzt: steuer( checkNum( betrag), checkNum( mwstSatz) ).

Funktionen verschachteln – Closures

In Javascript dürfen Funktionen in Funktionen deklariert werden – ein Feature, dass es nur in wenigen Programmiersprachen gibt (Javascript bemutzt Funktionen zur Definition von Objekten). Die innere Funktion ist dabei nur innerhalb der umgebenden Funktion verfügbar.

Seit Javascript 1.5 kann eine innere Funktion sogar innerhalb eines Anweisungsblocks erzeugt werden. Allerdings sind dann nur Funktionsaufrufe innerhalb des Blocks zugelassen.

Zur Laufzeit – beim Aufruf der äußeren Funktion – erzeugt der Javascript-Interpreter den Code der inneren Funktion. Dabei entsteht ein „Closure" der inneren Funktion – das ist der Code der Funktion und eine Referenz auf alle Variablen, die von der inneren Funktion benötigt werden (die innere Funktion hat Zugriff auf die Variablen und Parameter der äußeren Funktion). Ein Closure kombiniert den Programmcode mit der lexikalischen Umgebung – d.h. das Closure merkt sich die Umgebung, in der es erzeugt wurde.

Geben Sie ein oder zwei Beträge ein. Summen über 100 € werden um 50% gekürzt.

+ Summe

function outerFunction() {
   function getValue( id )    {
      if ( isNaN( parseInt( document.getElementById( id ).value ) ) ) {
      	return 0;
      }
      return parseInt( document.getElementById( id ).value );
   }

   var z = getValue( 'x' ) + getValue( 'y' );

   if (z > 100) {
      function cutter( z ) {
         return ( 100 + ( z - 100 ) / 2);
      }
      z = cutter(z);
      document.getElementById( 'zugr' ).style.display = "block";
   } else {
      document.getElementById( 'zugr' ).style.display = "none";
   }
   
   document.getElementById( 'z' ).value = z;
   return false;
}

Die innere Funktion getValue() liest den Wert eines Eingabefeldes und wandelt den Stringwert in einen Integerwert um. Wenn die Funktion keinen Zahlenwert findet, gibt sie 0 zurück.

Der Einsatz der inneren Funktion getValue() ist auch eine Gestaltungsfrage – wenn die Funktion in der Anwendung nur eine Nebenrolle spielt, macht es Sinn, sie innerhalb der äußeren Funktion zu verbergen, damit sich der Programmablauf klarer in der Folge der Funktionen wiederspiegelt. Mit demselben Hintergedanken sitzt die Funktion cutter() innerhalb der if-Anweisung – cutter() ist innerhalb des if-Blocks deklariert und kann nur innerhalb des if-Blocks aufgerufen werden.

Der Anstoß der Funktion outerFunction() erfolgt nach dem Laden des Dokuments in der Funktion initFunc(). initFunc prüft durch die Abfrage if (typeof( outerFunction ) != "undefined") bzw. if (typeof( getValue ) != "undefined"), ob die Funktion bekannt ist – getValue() wird nicht erkannt, weil die Funktion innerhalb von outFunktion() deklariert ist.

function initFunc() {
   var outerForm = document.getElementById( 'outerForm' );
   outerForm.onsubmit = function() {
   	if (typeof( outerFunction ) != "undefined") {
         outerFunction();
      	return false;
      }
   }

   var innerForm = document.getElementById( 'innerForm' );
   innerForm.onsubmit = function() {
      if (typeof( getValue ) != "undefined") {
         alert( "Und es gibt sie doch ..." );
      } else {
         alert( "Kein Zugriff auf die innere Funktion möglich" );
      }
      return false;
   }
}

Hinweis: Durch Closures ist es möglich, private Instanzvariablen in Objekten zu definieren.

   


Copyright © 2000 - 2010 Media Engineering Alle Rechte vorbehalten
Design + Programmierung Media EngineeringImpressum und Nutzungsbestimmungen