JavaScript – M+T Pocket . Das Programmier-Handbuch (Office Einzeltitel) [Taschenbuch]

6.4
Funktionen, Prozeduren und Methoden

Die Fähigkeit zu Bildung von Funktionen oder ähnlicher Strukturen ist ein Hauptkriterium einer modernen Programmiertechnik.
Funktionen bedeuten die Zusammenfassung von ein oder mehreren Befehl(en) zu
einem Block, der mit einem Namen bzw. Bezeichner benannt wird. Mit Funktionen kann
man Code effektiver gestalten, wenn in einem Script bestimmte Befehlsfolgen
öfter benötigt werden. Statt diese immer wieder benötigten Befehlsfolgen
jedesmal neu schreiben zu müssen, werden sie einfach über diesen Bezeichner
aufgerufen. Der Programmierer hat weniger Tipparbeit, die Wahrscheinlichkeit
für Flüchtigkeitsfehler sinkt und vor allem wird ein Script kleiner, da die
Anzahl der Zeichen reduziert wird. Damit wird eine Webseite schneller einem
Anwender zur Verfügung stehen[14].
In der Regel lohnt sich die Bildung einer Funktion bereits dann, wenn man eine
Schrittfolge mehr als einmal braucht. Ein weiterer wichtiger Aspekt ist, dass
eine Funktion Befehlsschritte vor der Ausführung beim Laden eines Scripts im
Rahmen der Webseite schützt. Oft ist das weder gewünscht noch sinnvoll. Erst
wenn bestimmte Voraussetzungen vorliegen (z.B. wenn der Anwender irgendwo hin
klickt, eine Webseite verlassen wird, bestimmte Eingaben durch den Anwender
abgeschlossen sind etc.), wird die Funktion über ihren Namen aufgerufen und die
Befehlsfolge ausgeführt.

6.4.1
Die Deklaration von Funktionen

Die Definition von Funktionen erfolgt, indem das dafür in
JavaScript vorgesehene Schlüsselwort function die Deklaration einleitet, dann der Bezeichner der Funktion folgt und abschließend ein Klammernpaar notiert wird, in
dem eventuell benötigte Parameter an die Funktion weitergegeben werden können.
Solche Parameter sind Werte, die dann innerhalb der Funktion verwendet werden
können. Dies sind dann Variablen, die in der Funktion lokal verwendet werden
können. Mehrere Parameter werden bei Bedarf mit Kommata getrennt in die
Klammern notiert. Anschließend folgt der Block mit den enthaltenen Anweisungen
– ohne (!), dass vorher ein Semikolon steht. Dies sieht schematisch also so aus:

function [Funktionsbezeichner]([optionale Parameter])
{

…irgendwelche Anweisungen

}

Der Aufruf einer JavaScript-Funktion kann an einer
beliebigen Stelle im Script (auch innerhalb einer anderen Funktion) über die
Angabe des Namens der Funktion oder über einen Eventhandler in HTML erfolgen
(das ist sowas wie onLoad
oder onClick,
was wir schon benutzt haben, aber noch genauer bekommen). Wenn im Script selbst
eine Funktion aufgerufen wird, muss sie mit dem Bezeichner, den Klammern,
eventuell notwendigen Übergabewerten und einem abschließenden Semikolon notiert
werden.

Oft wird im Umgang mit Funktionen das Angeben von
Klammern vergessen. Einer Funktion (und einer Methode – s.u.) muss so gut wie
immer (!!) ein Klammerpaar hinter dem Bezeichner folgen. Ob die Klammern leer
bleiben oder darin Parameter stehen, spielt keine Rolle. Es gibt (leider,
denn damit wird der Sprache eine wichtige Konsistenz entzogen) in JavaScript
zwar einige wenige Sondersituationen, wo dies unterbleiben kann. Sie treten
aber so selten auf, dass man wegen dieser Spezialfälle nicht auf die
nachdrücklichste Betonung von immer verzichten soll.

Der Name einer Funktion ist relativ frei wählbar. Nur
folgende Regeln dürfen nicht verletzt werden (sie sind identisch zu dem Fall
von Variablenbezeichnern):

1.
Das erste Zeichen eines Bezeichners muss ein Buchstabe oder der
Unterstrich _ sein.

2.
Es darf keines der in JavaScript gültigen Schlüsselworte als Bezeichner
verwendet werden.

3.
Ein Bezeichner darf keine Leerzeichen enthalten.

JavaScript unterscheidet natürlich auch bei Funktionen –
wie bei Variablenbezeichnern – streng zwischen Groß- und Kleinschreibung.

Ob nun ein Bezeichner aus Groß- oder Kleinbuchstaben besteht
oder man diese mischt, das ist im Prinzip egal. Allgemein hat sich aber
durchgesetzt, einen Funktionsbezeichner mit einem Kleinbuchstaben zu beginnen
und bei zusammengesetzten Bezeichnern jedes neue Teilwort mit einem
Großbuchstaben zu beginnen. Ebenso werden Bezeichner für Funktionen meist aus
Übertragungsgründen nicht zu groß gewählt. Das ist wie bei Variablen. Etwa so:

meineFkt()

ladeSeite()

holCookieWrt()

Wenn eine Schreibweise für Bezeichner von Funktionen einmal
gewählt wurde, sollten alle Bezeichner so geschrieben werden. Das bedeutet,
wenn der eine Bezeichner einer Funktion vollkommen klein geschrieben wird,
sollten auch alle Bezeichner von anderen Funktionen vollkommen klein
geschrieben werden. Eine inkonsequente Schreibweise in einer Webseite oder
einem Projekt – also mal klein, mal gemischt, mal groß – ist nicht verboten,
aber extrem unglücklich. Das gilt vollkommen analog für Bezeichner von
Variablen und anderen Syntaxelementen, die frei wählbare Bezeichner bekommen
können. Wenn Sie bei der Deklaration eine bestimmte Schreibweise gewählt haben,
muss diese insbesondere konsequent bei jedem Aufruf so geschrieben werden.
Insbesondere auch in Hinblick auf Groß- und Kleinbuchstaben.

Testen wir nun den Einsatz
von Funktionen in verschiedenen Konstellationen. Der Einsatz von lokalen und
globalen Variablen sowie Übergabewerten als auch der Aufruf per Event-Handler
und direkt in einer anderen Funktion wird erfolgen.

<HTML>

<HEAD>

<SCRIPT
language="JavaScript">

var global = 42;

function eins() {

alert("Wert der glabalen Variable: " +
global);

}

function zwei(a) {

alert(a + "nWert der glabalen Variable: " +
global);

}

function drei(b) {

var a = 5;

alert("Ergebnis der Multiplikation: " +
(a*b));

}

function vier(a,b) {

alert("Ergebnis der Multiplikation: " +
(a*b));

}

function lade() {

eins();

zwei("Gebe das an die Funktion zwei()
weiter.");

drei(5);

vier(5,8);

}

</SCRIPT>

</HEAD>

<BODY
onLoad="lade()">

</BODY>

</HTML>

Listing 6.7: Funktionen im Einsatz

In dem Script wird eine globale Variable mit dem Bezeichner global verwendet.
Die erste Funktion eins() besitzt
keinen Übergabeparameter und gibt einen fest einprogrammierten Text sowie der
Wert der globalen Variablen aus.

Die Funktion zwei() verwendet einen Übergabewert. Diese Variable wird
lokal a genannt
und zusammen mit einem fest einprogrammierten Text sowie dem Wert der globalen
Variablen ausgegeben. Beachten Sie die Kodierung n. Damit wird in dem String ein
Sonderzeichen kodiert, das einen Zeilenumbruch in dem Ausgabefenster auslöst.
Der Aufruf der Funktion übergibt den Text "Gebe das an die Funktion zwei() weiter.".

Die Funktion drei() verwendet auch einen Übergabewert. Diese Variable
wird lokal b
genannt. Sie ist aber diesmal vom Typ Number und wird mit einer weiteren lokalen
Variable a (wie
in Funktion zwei()
wieder bewußt identisch bezeichnet) multipliziert. Das Ergebnis wird zusammen
mit einem fest einprogrammierten Text sowie dem Wert der globalen Variablen
ausgegeben. Der Aufruf der Funktion übergibt den nummerischen Wert 5.

Die Funktion vier() verwendet zwei Übergabewerte. Diese Variablen
werden bewußt identisch zu anderen lokalen Variablen im Script a und b genannt und
multipliziert. Das Ergebnis wird zusammen mit einem fest einprogrammierten Text
ausgegeben. Der Aufruf der Funktion übergibt zwei nummerische Werte.

Nur die Funktion lade() wird beim Laden der Seite
aufgerufen. Diese wiederum lädt nacheinander die anderen vier Funktionen über
die Angabe ihres Bezeichners.

6.4.2
Rückgabewerte

Eine Funktion kann nun am Ende ihrer
Arbeit ein Ergebnis zurückgeben. Etwa, wenn Sie eine Funktion geschrieben
haben, die nach einer Berechnung das Ergebnis an den Aufrufer zurückgeben soll.
Das wird in JavaScript über das Schlüsselwort return, gefolgt von dem Rückgabewert, bewerkstelligt.

Eine Funktion mit Rückgabewert kann überall dort stehen, wo
eine Variable oder ein Literal stehen kann. Der Rückgabewert kann auch direkt
innerhalb der Bedingung einer Kontrollstruktur verwendet werden, oder einer
Variablen zugewiesen werden.

Das Schlüsselwort return hat den weiteren Effekt, dass an dieser Stelle die
Abarbeitung der Funktion abgebrochen und in die Zeile hinter dem
Funktionsaufruf zurückgesprungen wird. Das macht Sinn, wenn die Anweisung return nicht am
Ende der Funktion steht, sondern innerhalb einer Kontrollfluss-Struktur, sodass
unter gewissen Umständen die Funktion abgebrochen wird, in einer anderen
Situation aber weiter abgearbeitet werden kann. Eine Funktion mit Rückgabewert
sieht schematisch also so aus:

function [Funktionsbezeichner]([optionale Parameter])
{

…irgendwelche Anweisungen

return [Rückgabewert];

}

Schauen wir uns
ein paar Beispiele mit Rückgabewerten an, wobei wir teilweise etwas vorgreifen
müssen.

<HTML>

<HEAD>

<SCRIPT
language="JavaScript">

function alter() {

var gebdat = prompt(

"Geben Sie Ihr Geburtsjahr in zweistelliger Form
ein",

"");

var heute = new Date();

return (((heute.getYear())%100 +
2000) – gebdat);

}

function lade() {

alert("Sie sind " + alter() + " Jahre
alt.");

}

</SCRIPT>

</HEAD>

<BODY
onLoad="lade()">

</BODY>

</HTML>

Listing 6.8: Rückgabewerte von Funktionen

In dem Script wird eine Funktion alter() verwendet, die das Ergebnis
einer Berechnung zurückliefert. Konkret wird der Anwender aufgefordert, sein
Geburtsjahr in zweistelliger Form einzugeben.

Über Anwendung eines Date-Objekts und der darüber zur
Verfügung stehende Methode getYear()
wird das aktuelle Datum ermittelt und daraus das Jahr extrahiert. Die Formel
selbst ist nicht ganz trivial, was darauf zurückgeführt werden muss, dass
verschiedene Browser das Date-Objekt
unterschiedlich verwenden. Das bedeutet, manche Browser interpretieren das Jahr
ab einem Zeitpunkt 1900,
andere ab dem Jahr 0.
Mit diesem Verfahren wird dieses unterschiedliche Verhalten kompensiert. Von
dem so ermittelten Jahr wird das Geburtsdatum abgezogen und dieses Ergebnis an
den Aufrufer der Funktion alter() zurückgegeben.
Das ist die Funktion lade().
Dort wird die Funktion innerhalb von alert() aufgerufen. An der Stelle des
Aufrufs steht dann bei der Ausgabe der Rückgabewert.

Beachten Sie, dass das Script nicht gegen Fehleingaben
durch den Anwender abgesichert ist. Wenn dieser Text, eine falsche Anzahl von
Stellen oder nichts eingibt, wird kein sinnvoller Wert zurückgegeben. Aber
das soll hier nicht von Bedeutung sein.

Da folgende Beispiel verwendet eine Entscheidungsstruktur –
die if-Abfrage.

<HTML>

<HEAD>

<SCRIPT
language="JavaScript">

function alter(){

var gebdat = prompt("Geben Sie Ihr Geburtsjahr
in vierstelliger Form ein","");

var heute = new Date();

if((((heute.getYear())%100 + 2000) –
gebdat)<18) {

return false;

}

else {

return true;

}

}

function lade() {

if(alter()) {

alert("Willkommen.");

}

else {

alert("Zugang nur für Erwachsene.");

}

}

</SCRIPT>

</HEAD>

<BODY
onLoad="lade()">

</BODY>

</HTML>

Listing 6.9: Der Einsatz von return in
Entscheidungsstrukturen

In dem Script wird eine Funktion alter() verwendet, die diesmal nicht das
Alter als Ergebnis einer Berechnung zurückliefert, sondern einen Wahrheitswert,
ob eine bestimmte Bedingung (ein Mindestalter) erfüllt ist (true) oder nicht (false). Konkret
wird der Anwender wieder aufgefordert, sein Geburtsjahr einzugeben. Ist das
berechnete Alter kleiner als 18,
wird der eine Zweig der if-Entscheidung
gewählt, ansonsten der andere. Dabei sollte beachtet werden, dass die Funktion
direkt in der Bedingungsüberprüfung steht und der Rückgabewert direkt verwendet
wird.

210 116
/fkt3b

6.15: Erlaubnis nicht erteilt

135 116
/fkt3c

6.16: Erlaubnis erteilt

Funktionen ohne Rückgabewert –
Prozeduren

Wenn nun eine Funktion keinen Rückgabewert zurückgibt, wird
das in den meisten Programmiersprachen als Procedure oder – eingedeutscht –
Prozedur bezeichnet. Dort wird das auch in der Regel bei der Deklaration von
einem anderen Schlüsselwort wie eine Funktion gekennzeichnet. Von der Logik her
bedeutet dies, dass bei Funktionen (auch) das Ergebnis einer Operation von
Bedeutung sein sollte, während die Operation einer Prozedur reiner Selbstzweck
ist. JavaScript unterscheidet die beiden eng verwandten Techniken überhaupt
nicht. Eine Funktion muss nicht mehr einen Rückgabewert liefern oder zumindest
als "ohne Rückgabewert" definiert werden. Überhaupt behandelt
JavaScript Funktionen sehr locker. Von der Syntax sehr streng strukturierte
Sprachen verlangen, dass der Rückgabewert einer Funktion auch von der
aufrufende Stelle verwendet werden muss (!). Das bedeutet, ein Aufruf einer
Funktion ist dort nur dann möglich, wenn der Rückgabewert einer Variablen
zugewiesen oder sonst verwendet wird (etwa in Vergleichen einer
Kontrollstruktur). JavaScript ist da weniger streng. Eine Funktion kann aufgerufen
werden, ohne dass der Rückgabewert irgendwo in der Folge im Script zu Kenntnis
genommen wird. Dies ist zwar ein Verhalten, das den Umgang mit Funktionen erst
einmal erleichtert, aber sowohl bei Unachtsamkeit Fehler produzieren kann als
auch die Suche von Fehlern erschwert, wenn etwas schiefgeht.

Methoden

Sowohl Funktionen als auch Prozeduren gibt es in streng
objektorientierten Sprachen nicht. Dort übernimmt eine verwandte Technik deren
Funktionalität – die so genannten Methoden. Dabei handelt es sich eigentlich
nur um Funktionen oder Prozeduren, die nur über ihr zugehöriges Objekt
verwendet werden können. Wir kennen da schon einige Fälle:

Die Methode write(),
die über ein documentObjekt verwendet wird (document.write()).

Die Methode getYear(),
die über ein Date-Objekt
verwendet wird.

Die Methoden alert()
und prompt().
Auch das sind Methoden und keine Funktionen. Sie wurde bisher zwar (scheinbar)
ohne zugehöriges Objekt verwendet, aber das scheint eben nur so. Man kann dann
eine Methode ohne vorangestelltes Objekt verwenden, wenn man sich im
"Inneren" des Objektes befindet. Das ist so, wie bei Angaben auf
Verzeichnisebene. Wenn man sich in einem Verzeichnis befindet, kann bei einer
relativen Angabe auf die Voranstellung des absoluten Pfades verzichten. Die
Methoden gehören zu einem Objekt, das window heisst und alle im Browser
befindlichen Elemente enthält. Die Syntax alert() ist also gleichbedeutend wie window.alert().

In einer syntaktisch sehr lockeren und hybrid (sowohl
objektorientierte Bestandteile, aber auch prozdurale) aufgebauten Sprache wie
JavaScript ist es nicht unbedingt nötig, von der Terminologie her streng
zwischen Funktionen und Methoden trennen, obwohl es eigentlich ein bißchen
schlampig ist.

JavaScript kennt einige vorgefertigte Funktionen. Wir
werden die wichtigsten davon kennenlernen.