-
Notifications
You must be signed in to change notification settings - Fork 17
/
funktionen.html
252 lines (236 loc) · 17.8 KB
/
funktionen.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>JavaScript: Funktionen</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="js-doku.css">
</head>
<body>
<div id="nav">
<p>Hier entsteht eine <strong>JavaScript-Dokumentation</strong> von <a href="https://molily.de/">molily</a>. Derzeit ist sie noch lückenhaft, wächst aber nach und nach. Kommentare und Feedback werden gerne per <a href="mailto:[email protected]">E-Mail</a> entgegen genommen.</p>
<p class="contents-link"><a href="./">Zum Inhaltsverzeichnis</a></p>
</div>
<h1>JavaScript: Funktionen</h1>
<div class="section" id="function">
<h2>Einführung</h2>
<p>Mit Funktionen können Sie flexible Teilprogramme notieren, die sie wiederholt aufrufen können. Funktionen sind ein einfaches Mittel, ein JavaScript-Programm zu strukturieren.</p>
<p>In JavaScript haben Funktionen einen höheren Stellenwert als in anderen Programmiersprachen und haben einige Besonderheiten. JavaScript besitzt Aspekte einer <em>funktionalen Programmiersprache</em>. In JavaScript sind Funktionen nicht feste, einmal definierte Teilprogramme, sondern selbst Werte, mit denen Sie im Programm arbeiten können. Sie können neue Funktionen zur Laufzeit erzeugen. Nicht mehr benötigte Funktionen werden wieder gelöscht.</p>
<p>Sie können <strong>eigene Funktionen</strong> auf verschiedene Arten definieren. Sie können Funktionen als lokale Variable in einer anderen Funktion erzeugen. Sie können Funktionen auch an Objekte hängen. Das bedeutet, sie als <a href="objekte.html">Eigenschaft</a> eines Objekts zu speichern. Der Fachbegriff dafür in der objektorientierten Programmierung ist <a href="objekte.html#methoden">Methode</a>. Und schließlich können Sie auch anonyme (namenlose) Funktionen anlegen, um sie z.B. als Parameter an eine andere Funktion zu geben.</p>
</div>
<div class="section" id="deklarationen">
<h2>Funktionsdeklarationen</h2>
<p>Die einfachste und wichtigste Art, eine Funktion zu definieren, ist die sogenannte <dfn>Funktions-Deklaration</dfn> (auf englisch <em lang="en">function declaration</em>). Deren Syntax ist folgendermaßen aufgebaut:</p>
<pre>
function <var>Funktionsname</var>(<var>Parameterliste</var>) {
<var>Anweisungen</var>
}
</pre>
<p>Der <strong>Funktionsname</strong> muss <a href="variablen.html#bezeichner">den üblichen Anforderungen an JavaScript-Bezeichner</a> genügen: Sie dürfen Buchstaben, Dezimalziffern (0-9), das Dollarzeichen ($) sowie den Unterstrich (_) verwenden. Ziffern dürfen nicht an erster Stelle stehen.</p>
<p>Die <strong>Parameterliste</strong> zwischen den beiden runden Klammern ist eine durch Kommas getrennte Liste von Namen. Für diese gelten die besagten Namenskonventionen. Innerhalb der Funktion können Sie auf die übergebenen Parameter zugreifen, indem Sie die hier vergebenen Namen verwenden.</p>
<p>Zwischen den beiden geschweiften Klammern wird der <dfn>Funktionskörper</dfn> notiert: Darin werden die <a href="syntax.html#anweisungen">Anweisungen</a> untergebracht, die beim Aufruf der Funktion ausgeführt werden sollen.</p>
<p>Folgendes Beispiel soll das Schema verdeutlichen:</p>
<pre>
function statusMeldung(meldungsTyp, meldungsText) {
var ausgabeElement = document.getElementById('meldungsausgabe');
ausgabeElement.className = meldungsTyp;
ausgabeElement.innerHTML = meldungsText;
}
statusMeldung(
'fehler',
'Beim Absenden Ihrer Nachricht ist ein Fehler aufgetreten.'
);
</pre>
<p>Das Beispiel definiert eine Funktion mit dem Namen <code>statusMeldung</code>. Die Funktion erwartet zwei Parameter mit den Namen <code>meldungsTyp</code> und <code>meldungsText</code>. Sie sucht ein Element im Dokument mit der ID <code>meldungsausgabe</code>. Dann setzt sie dessen Klasse auf den Wert des Parameters <code>meldungsTyp</code> und füllt das Element mit dem Wert des Parameters <code>meldungsText</code>.</p>
<p>Eine Funktion wird nach dem Schema <code><var>Funktionsname</var>(<var>Parameterliste</var>)</code> aufgerufen. Die Parameterliste beim Aufruf ist eine durch Komma getrennte Liste an <a href="syntax.html#ausdruecke">Ausdrücken</a> (Namen oder Werten). Der Funktion im Beispiel werden zwei Parameter übergeben, die als <a href="kernobjekte.html#string">String-Literale</a> notiert werden.</p>
<p>Dies führt dazu, dass <code>meldungsTyp</code> in der Funktion den Wert <code>'fehler'</code> bekommt und <code>meldungsText</code> den Wert <code>'Beim Absenden Ihrer Nachricht ist ein Fehler aufgetreten.'</code>.</p>
<!-- TODO: Scope: Eine Funktionsdeklaration erzeugt einen Namen im aktuellen Geltungsbereich. Wenn eine Funktionsdeklaration innerhalb einer Funktion notiert werden, wird ein Name im Funktions-Geltungsbereich registriert. Steht die Deklaration außerhalb jeder Funktion, dann wird ein Name im globalen Geltungsbereich angelegt. -->
</div>
<div class="section" id="ergebnis">
<h2>Rückgabewert (Ergebnis)</h2>
<p>Eine Funktion kann nicht nur Werte entgegen nehmen, sondern auch einen Wert zurückgeben. Dieser Wert heißt <dfn>Rückgabewert</dfn> oder auch <dfn>Ergebnis</dfn>. Der Wert kann an der Stelle benutzt werden, an der der Funktionsaufruf steht. Der Funktionsaufruf <em>ergibt</em> den Wert.</p>
<p>Denken Sie an eine einfache mathematische Funktion: <code>f(x) = x²</code>. Für x = 5 ergibt die Funktion 25, für x = 6 ergibt die Funktion 36 usw.</p>
<p>In JavaScript könnte die Funktion so aussehen:</p>
<pre>
function quadrat(x) {
<strong>return</strong> x * x;
}
window.alert( quadrat(5) );
</pre>
<p>Mit der <code>return</code>-Anweisung können Sie die Funktion beenden und einen Wert zurückgeben. Nach dem Schlüsselwort <code>return</code> folgt ein beliebiger <a href="syntax.html#ausdruecke">Ausdruck</a>. Die Anweisung wird mit einem Semikolon abgeschlossen.</p>
<p>Im Beispiel wird die Funktion <code>quadrat</code> mit dem Parameter 5 aufgerufen. Der Ausdruck <code>x * x</code> ergibt 25, also wird der Wert 25 zurückgegeben.</p>
<p>Das Ergebnis 25 wird an der Stelle eingefügt, an der der Funktionsaufruf stand. Aus <code>window.alert( quadrat(5) )</code> wird also <code>window.alert( 25 )</code>.</p>
<p>Bei der Funktionsausführung kann <code>return</code> nur einmal ausgeführt werden, denn es beendet die Ausführung sofort und sorgt dafür, dass die Ausführung dort weitergeht, wo die Funktion aufgerufen wurde.</p>
<p>Das heißt aber nicht, dass Sie in einer Funktion nicht mehrere <code>return</code>-Anweisungen verwenden können. <code>return</code> kann mehrfach vorkommen, muss aber in unterschiedlichen logischen Zweigen stehen. Zum Beispiel:</p>
<pre>
function begrüßung(person) {
if (person.nickname) {
<strong>return</strong> 'Willkommen ' + person.nickname;
} else {
<strong>return</strong> 'Hallo ' + person.vorname;
}
}
var person1 = {
vorname: 'Erika'
};
var person2 = {
vorname: 'Max',
nickname: 'zimtschnecke'
};
window.alert( begrüßung(person1) );
window.alert( begrüßung(person2) );
</pre>
<p>Das Beispiel definiert eine Funktion <code>begrüßung</code>, die ein <code>person</code>-Objekt als Parameter erwartet. Darin befindet sich eine <a href="syntax.html#kontrollstrukturen">bedingte Anweisung</a>. Sie prüft, ob das übergebene Objekt eine Eigenschaft <code>nickname</code> besitzt. Falls ja, gibt sie eine Begrüßung zurück, die <code>nickname</code> verwendet. Falls nein, gibt sie eine Begrüßung zurück, die die Eigenschaft <code>vorname</code> verwendet.</p>
<p>Die Funktion wird zweimal aufgerufen. Einmal mit dem Objekt <code>person1</code>, das einen Nickname besitzt. Einmal mit dem Objekt <code>person2</code>, das keinen Nickname besitzt. Die Fallunterscheidung in der Funktion bestimmt nun den Rückgabewert: Im ersten Fall wird <code>'Hallo Erika!'</code> zurückgegeben, im zweiten Fall <code>'Willkommen zimtschnecke'</code>.</p>
<p>Die <code>return</code>-Anweisung beendet die Funktionsausführung wie gesagt. Das heißt, wir können die Funktion <code>begrüßung</code> auch folgendermaßen definieren:</p>
<pre>
function begrüßung(person) {
if (person.nickname) {
<strong>return</strong> 'Willkommen ' + person.nickname;
}
<strong>return</strong> 'Hallo ' + person.vorname;
}
</pre>
<p>Sie können sich den <code>else</code>-Zweig sparen. Wenn die Bedingung der <code>if</code>-Anweisung erfüllt ist, springt der JavaScript-Interpreter sofort aus der Funktion heraus. Dieses Muster wird häufig verwendet, um eine Funktion vorzeitig zu beenden. Ein weiteres Beispiel:</p>
<pre>
function hypotenuse(a, b) {
if (a <= 0 || b <= 0) {
return 0;
}
var c = Math.sqrt(a * a + b * b);
return c;
}
</pre>
<p>Das Beispiel berechnet die Länge der Hypotenuse in einem rechtwinkligen Dreieck anhand des <a href="https://de.wikipedia.org/wiki/Satz_des_Pythagoras">Satzes des Pythagoras</a>. Die Formel dafür lautet
<math>
<mi>c</mi>
<mo>=</mo>
<msqrt>
<msup>
<mi>a</mi>
<mn>2</mn>
</msup>
<mo>+</mo>
<msup>
<mi>b</mi>
<mn>2</mn>
</msup>
</msqrt>
</math>.</p>
<p>Wenn die Längen der Katheten <code>a</code> und <code>b</code> kleiner oder gleich 0 sind, dann ist eine Berechnung nicht möglich oder würde einen fehlerhaften Wert ergeben. Gegebenenfalls wird die Funktion vorzeitig beendet und sie gibt 0 zurück. Erst nach dieser Prüfung folgt die eigentliche Berechnung der Hypotenuse <code>c</code>.</p>
<!-- TODO: Beenden ohne Rückgabewert: return; -->
</div>
<div class="section" id="funktionsvariablen">
<h2>Funktionsvariablen</h2>
<p>Innerhalb von Funktionen können Sie Variablen deklarieren, deren Geltungsbereich auf die Funktion beschränkt ist. Die obige Beispielfunktion <code>hypotenuse</code> hat eine Variable definiert, nämlich <code>c</code>:</p>
<pre>
function hypotenuse(a, b) {
if (a <= 0 || b <= 0) {
return 0;
}
var <strong>c</strong> = Math.sqrt(a * a + b * b);
return <strong>c</strong>;
}
</pre>
<p>Die Variable ist nur innerhalb der Funktion verfügbar, aber deren Wert soll nach außen gegeben werden. Das ist mit der besprochenen <code>return</code>-Anweisung möglich.</p>
<p>Eine genaue Erklärung von Funktionsvariablen finden Sie im <a href="variablen.html#funktionsvariablen">Kapitel über Variablen</a>.</p>
</div>
<div class="section" id="ausdruecke">
<h2>Funktionsausdrücke</h2>
<p>Die vorgestellte Funktionsdeklaration vereint zwei Aufgaben: Sie erzeugt eine Funktion und speichert diese gleichzeitig unter einem Namen im aktuellen <a href="variablen.html#scope">Geltungsbereich</a>.</p>
<p>Folgende Funktionsdeklaration speichert unter dem Namen <code>quadrat</code> eine Funktion.</p>
<pre>
function quadrat(x) {
return x * x;
}
</pre>
<p>Es ist jedoch nicht immer gewünscht, einer Funktion einen Namen zu geben und diesen im aktuellen Geltungsbereich verfügbar zu machen. Manchmal möchte man eine Funktion erzeugen, ohne sie unter einem Namen verfügbar zu machen.</p>
<p>Es gibt daher noch eine weitere Schreibweise, um Funktionen zu erzeugen: Den <dfn>Funktions-Ausdruck</dfn> (englisch <em lang="en">function expression</em>).</p>
<p>Syntaktisch gesehen ist eine Funktionsdeklaration eine <a href="syntax.html#anweisungen"><em>Anweisung</em></a>. Ein Funktionsausdruck hingegen ist ein <a href="syntax.html#ausdruecke"><em>Ausdruck</em></a>, wie der Name schon sagt. Damit haben beide unterschiedliche Anwendungsmöglichkeiten. Sie können Funktionsausdrücke an mehr Stellen notieren als eine Funktionsdeklaration.</p>
<p>Das Schema eines Funktionsausdruckes sieht folgendermaßen aus:</p>
<pre>function (<var>Parameterliste</var>) { <var>Anweisungen</var> }</pre>
<p>Ein Funktionsausdruck erzeugt lediglich eine Funktion, speichert sie aber nicht automatisch unter einem Namen. Man spricht daher auch von <dfn>anonymen (namenlosen) Funktionen</dfn>.</p>
<p>Das Ergebnis des Ausdruckes ist ein Funktionsobjekt. Sie können es wie jeden anderen Wert in JavaScript beliebig weiterverwenden. Beispielsweise können Sie das erzeugte Funktionsobjekt in einer Variable speichern:</p>
<pre>var <var>Funktionsname</var> = function (<var>Parameterliste</var>) { <var>Anweisungen</var> };
</pre>
<p>Diese Variablenzuweisung mit Funktionsausdruck hat den gleichen Effekt wie die klassische Funktionsdeklaration <code>function <var>Funktionsname</var>(…) {…}</code>. Bis auf einige Sonderfälle sind die beiden Schreibweisen austauschbar.</p>
<p>Was sind nun die <strong>Vorteile</strong> eines Funktionsausdruckes?</p>
<p>Eine Funktion, die Sie mit einem Funktionsausdruck erzeugen, können Sie direkt an ein Objekt als <a href="objekte.html#methoden">Methode</a> hängen. Auf diese Weise können Sie Ordnung in Ihre Scripte bringen und zusammenhörige Werte und Funktionen unter einem Objekt gruppieren. Ein Beispiel:</p>
<pre>
var bildergalerie = {
abspielen: <strong>function () {</strong>
/* … */
<strong>}</strong>
};
bildergalerie.abspielen();
</pre>
<p>Im obigen Beispiel wird eine Objekt mittels <a href="objekte.html#object-literale">Object-Literal</a> erzeugt und in der Varialben <code>bildergalerie</code> gespeichert. Dem Objekt wird eine Methode leeren Objekt eine Methode namens <code>abspielen</code> hinzugefügt.</p>
<p>Die entsprechende Funktion wird als Funktionsausdrucks notiert. Das entstehende Funktionsobjekt wird in der Eigenschaft <code>abspielen</code> gespeichert. Schließlich wird die Funktion als Methode aufgerufen.</p>
<p>Das obige Beispiel ließe sich übrigens auch mit einer Funktionsdeklaration lösen:</p>
<pre>
<strong>function abspielen() {</strong>
/* … */
<strong>}</strong>
var bildergalerie = {
abspielen: abspielen
};
bildergalerie.abspielen();
</pre>
<p>Hier wird zunächst eine Funktion <code>abspielen</code> erzeugt. Dann wird sie in der gleichnamigen Eigenschaft des Objekts <code>bildergalerie</code> gespeichert.</p>
<p>Warum ist es sinnvoller, hier einen Funktionsausdruck zu verwenden?</p>
<p>Zunächst einmal ist die Schreibweise mit Funktionsausdruck kompakter. Wichtiger ist aber, dass nur ein Name, nämlich <code>bildergalerie</code> belegt wird. Die Schreibweise mit Funktionsdeklaration belegt einen weiteren Namen, <code>abspielen</code>. Dies ist unnötig und kann zu Konflikten führen, wenn andere Scripte denselben Namen verwenden.</p>
<p>Funktionsausdrücken werden häufig verwenden, wenn eine Funktion an eine andere Funktion übergeben wird. Das passiert beispielsweise bei der <a href="event-handling-fortgeschritten.html">fortgeschrittenen Ereignis-Verarbeitung</a>.</p>
<p>Die Variante mit Funktionsdeklaration sähe so aus:</p>
<pre>
function init() {
window.alert('Dokument ist fertig geladen!');
}
window.addEventListener('load', init);
</pre>
<p>Im Beispiel wird eine Funktion namens <code>init</code> angelegt und als Event-Handler für das <code>load</code>-Ereignis beim <code>window</code>-Objekt registriert. Die Funktion wird der Methode <a href="event-handling-fortgeschritten.html#addEventListener">addEventListener</a> die Funktion <code>init</code> als Parameter übergeben.</p>
<p>Diese Schreibweise ist sinnvoll, wenn Sie die Funktion <code>init</code> später noch einmal benötigen. Üblicherweise ist das nicht der Fall: Man braucht die Funktion nur einmal, um sie als Handler zu registrieren. Es ist nicht nötig, sie unter einem Namen zu speichern.</p>
<p>Ein Funktionsausdruck kann den Code vereinfachen. Notieren Sie die Handler-Funktion mit einem Ausdruck und übergeben Sie die erzeugte Funktion direkt an <code>addEventListener</code>:</p>
<pre>
window.addEventListener('load', <strong>function() {
window.alert('Dokument ist fertig geladen!');
}</strong>);
</pre>
<p>Es gibt noch weitere Fälle, in denen das Benennen und Zwischenspeichern einer Funktion unnötig ist. Damit gibt es es weitere Anwendungsmöglichkeiten für Funktionsausdrücke. Im Abschnitt über <a href="#closures">Closures</a> werden wir darauf zurückkommen. <!-- TODO: werden wir? --></p>
</div>
<div class="section" id="arguments">
<h2>Variable Parameterzahl: Der arguments-Array</h2>
<p></p>
</div>
<div class="section" id="closures">
<h2>Verschachtelte Funktionen (Closures)</h2>
<!-- TODO: Beispiel als variablen.html (installiereKlickZähler) nutzen -->
<p>Siehe <a href="organisation-verfuegbarkeit.html#closures">Einführung in Closures</a></p>
</div>
<div class="section" id="funktional">
<h2>Funktionale Programmierung: Funktionen als Werte</h2>
<p>Funktionen sind ganz normale Objekte mit Eigenschaften und Methoden</p>
<p>Event-Handler und Callback-Funktionen</p>
<p>Funktionale Programmierung</p>
</div>
<div class="section" id="this">
<h2>Kontext einer Funktion: Das Schlüsselwort this</h2>
<p>Siehe <a href="organisation-verfuegbarkeit.html#this">Bedeutung von this</a></p>
<p>Aufrufweise bestimmt den this-Kontext</p>
<p>objekt.methode() vs. var m = objekt.methode(); m();</p>
<p>Function Binding, Function.prototype.bind</p>
<p>Kontext mit <code>call</code> und <code>apply</code> beeinflussen</p>
</div>
<div class="sequence-navigation">
<p class="next"><a href="werkzeuge.html" rel="next">Arbeitstechniken und Entwicklerwerkzeuge</a></p>
<p class="prev"><a href="objekte.html" rel="prev">Objekte</a></p>
</div>
<div id="footer">
<p><strong>JavaScript-Dokumentation</strong> · <a href="./">Zum Inhaltsverzeichnis</a></p>
<p>Autor: <a href="https://molily.de/">molily</a> · Kontakt: <a href="mailto:[email protected]">[email protected]</a></p>
<p>Lizenz: <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/de/">Creative Commons Namensnennung - Weitergabe unter gleichen Bedingungen 3.0</a></p>
<p><a href="https://github.com/molily/javascript-einfuehrung">JavaScript-Einführung auf Github</a></p>
<p>Kostenloses Online-Buch und E-Book:<br><a href="https://testing-angular.com" lang="en" hreflang="en">Testing Angular – A Guide to Robust Angular Applications</a> (englisch)</p>
</div>
<script src="js-doku.js"></script>
</body>
</html>