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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
|
---
title: Funktionen
slug: Web/JavaScript/Guide/Funktionen
tags:
- Beginner
- Functions
- Guide
- JavaScript
- 'l10n:priority'
translation_of: Web/JavaScript/Guide/Functions
---
<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Schleifen_und_Iterationen", "Web/JavaScript/Guide/Ausdruecke_und_Operatoren")}}</div>
<p class="summary">Funktionen sind ein Grundbaustein in JavaScript. Eine Funktion ist eine Prozedur - eine Reihe von Anweisungen, um eine Aufgabe auszuführen oder eine Wert auszurechnen. Um Funktionen zu verwenden, müssen diese im Scope (Gültigkeitsbereich) deklariert werden, in dem sie ausgeführt werden soll.</p>
<p>Siehe ebenfalls in der <a href="/de/docs/Web/JavaScript/Reference/Functions">ausführlichen Referenz über JavaScript Funktionen</a> nach, um noch mehr Detail zu erfahren.</p>
<h2 id="Funktionen_definieren">Funktionen definieren</h2>
<h3 id="Funktionsdeklaration">Funktionsdeklaration</h3>
<p>Eine <strong>Funktionsdefinition</strong> (auch <strong>Funktionsdeklaration </strong>oder <strong>Funktionsanweisung</strong> genannt) besteht aus dem Schlüsselwort <a href="/de/docs/Web/JavaScript/Reference/Statements/function" title="function"><code>function</code></a>, gefolgt von:</p>
<ul>
<li>Den Namen der Funktion.</li>
<li>Eine Liste von Parametern, die in runden Klammern geschrieben sind und durch Kommas getrennt sind.</li>
<li>Die JavaScript Anweisungen, die durch die Funktion definiert werden und innerhalb von geschweiften Klammern steht<code>.</code></li>
</ul>
<p>Das folgende Beispiel definiert eine Funktion mit dem Namen <code>square</code>:</p>
<pre class="brush: js">function square(number) {
return number * number;
}
</pre>
<p>Die Funktion <code>square </code>nimmt einen Parameter entgegen, welcher <code>number</code> heißt. Die Funktion besteht aus einer Anweisung, die besagt, dass der Parameter der Funktion (das ist <code>number</code>), multipliziert mit sich selbst, zurückgegeben werden soll. Dabei gibt das <a href="/de/docs/Web/JavaScript/Reference/Statements/return" title="return"><code>return</code></a> Statement an, welcher Wert von der Funktion zurückzugeben wird.</p>
<pre class="brush: js">return number * number;
</pre>
<p>Bei Primitive Parameter, wie Zahlen, wird der Funktionen <strong>der Wert</strong> übergeben. Werte, die der Funktion übergeben wurden und innerhalb der Funktion geändert werden, ändert den Wert zwar innerhalb der Funktion, <strong>aber nicht global oder in der aufrufenden Funktion</strong>.</p>
<p>Wird ein Objekt als Parameter übergeben (z. B. ein nicht primitiver Wert wie ein {{jsxref("Array")}} oder ein selbst definiertes Objekt) und die Funktion ändert die Objekteigenschaften, so sind die Änderungen außerhalb der Funktion sichtbar, wie im folgendem Beispiel veranschaulicht wird:</p>
<pre class="brush: js">function myFunc(theObject) { //Funktiondekleration
theObject.make = 'Toyota';
}
var mycar = {make: 'Honda', model: 'Accord', year: 1998};
var x, y;
x = mycar.make; // x bekommt den Wert "Honda"
myFunc(mycar);
y = mycar.make; // y bekommt den Wert "Toyota"
// (die make Eigenschaft wurde in der Funktion geändert)</pre>
<h3 id="Funktionsausdrücke">Funktionsausdrücke</h3>
<p>Während die Funktionsdeklarationen oben syntaktisch ein Statement sind, kann eine Funktion auch durch <a href="https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/function">Funktionsausdrücke</a> erstellt werde. Derartige Funktionen können auch <strong>anonym</strong> sein; denn Funktionen benötigten keinen Namen. So kann zum Beispiel die Funktion <code>square</code> auch so definiert werden:</p>
<pre class="brush: js">var square = function(number) { return number * number; };
var x = square(4); // x bekommt den Wert 16</pre>
<p>Jedoch kann die Funktion auch einen Name haben, um sich innerhalb der Funktion selbst aufzurufen oder die Funktion im Stack Traces des Debuggers zu identifizieren zu können:</p>
<pre class="brush: js">var factorial = function fac(n) { return n < 2 ? 1 : n * fac(n - 1); };
console.log(factorial(3));
</pre>
<p>Funktionsausdrücke sind praktisch, um Funktionen als ein Argument einer anderen Funktion zu übergeben. Das folgende Beispiel zeigt die Definition einer <code>map</code> Funktion, die eine Funktion als ersten Parameter erwartet:</p>
<pre class="brush: js">function map(f, a) {
var result = [],i; // erstellt ein neues Array
for (i = 0; i != a.length; i++)
result[i] = f(a[i]);
return result;
}
</pre>
<p>Im folgenden Quelltext wird einer Funktion eine Funktion übergeben, welche zuvor durch einen Funktions-Ausdruck definiert wurde. Diese Funktion wird für jedes Element in einem Array (zweiter Parameter) ausgeführt.</p>
<pre class="brush: js">function map(f, a) {
var result = []; // erstellt ein neues Array
var i;
for (i = 0; i < a.length; i++) {
result[i] = f(a[i]);
}
return result;
}
var f = function(x) {
return x * x * x;
}
var numbers = [0, 1, 2, 5, 10];
var cube = map(f,numbers);
console.log(cube);
</pre>
<p>gibt [0, 1, 8, 125, 1000] zurück.</p>
<p>In JavaScript kann eine Funktion definiert werden, wenn eine Bedingung erfüllt ist. Zum Beispiel wird <code>myFunc</code> nur definiert, wenn <code>num </code>gleich <code>0 </code>ist:</p>
<pre class="brush: js">var myFunc;
if (num === 0) {
myFunc = function(theObject) {
theObject.make = 'Toyota';
}
}</pre>
<p>Im Unterschied zu den hier gezeigten Funktionsdeklarationen, kann man auch den {{jsxref("Function")}} Konstruktor verwenden, um eine Funktion von einem String zur Laufzeit zu erstellen, ähnlich der {{jsxref("eval()")}} Funktion.</p>
<p>Eine <strong>Methode</strong> ist eine Funktion, die Eigenschaft eines Objektes ist. Mehr Informationen über Objekt und Methoden sind im Artikel "<a href="/de/docs/Web/JavaScript/Guide/Mit_Objekten_arbeiten">Mit Objekten arbeiten</a>" zu finden.</p>
<h2 id="Aufruf_von_Funktionen">Aufruf von Funktionen</h2>
<p>Das Definieren einer Funktion führen diese noch nicht aus. Die Definition gibt der Funktion lediglich einen Namen und beschreibt was geschehen soll, wenn die Funktion aufgerufen wird. Erst der <strong>Aufruf</strong> ermöglicht es die Aktionen mit den angegebenen Parametern durchzuführen. Zum Beispiel wird die vorher definierte Funktion <code>square</code> so aufgerufen:</p>
<pre class="brush: js">square(5);
</pre>
<p>Es wird die Funktion mit dem Argument 5 aufgerufen. Die Funktion führt ihre Anweisungen aus und gibt den Wert 25 zurück.</p>
<p>Funktionen müssen im Scope (Gültigkeitsbereich) sein, wenn sie aufgerufen werden, können jedoch auch erst später definiert werden, wie im folgenden Beispiel:</p>
<pre class="brush: js">console.log(square(5));
/* ... */
function square(n) { return n * n; }
</pre>
<p>Der Scope einer Funktion ist die Funktion in der sie deklariert wird, oder das gesamte Programm, falls sie auf oberster Ebene deklariert wird.</p>
<div class="note">
<p><strong>Hinweis:</strong> Nur die oben angegebene Syntax für Funktionen wird funktionieren (<code>function funcName(){}</code>). Der folgende Code funktioniert nicht. Das bedeutet, dass das nur mit Funktionsdeklarationen funktioniert aber nicht mit Funktionsausdrücken.</p>
</div>
<pre class="brush: js example-bad">console.log(square); // square ist mit dem Initialwert undefined gehoisted.
console.log(square(5)); // TypeError: square is not a function
var square = function(n) {
return n * n;
}
</pre>
<p>Die Argumente einer Funktion sind nicht auf Strings und Nummern limitiert, denn es können auch ganze Objekte übergeben werden. Die <code>showProps()</code> Funktion (definiert in Beitrag "<a href="/de/docs/Web/JavaScript/Guide/Mit_Objekten_arbeiten#Objekte_und_Eigenschaften" title="https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Working_with_Objects#Objects_and_Properties">Arbeiten mit Objekten</a>") ist ein Beispiel für einer Funktion, die Objekte als Argument entgegennimmt.</p>
<p>Eine Funktion kann sich selbst Aufrufen. Zum Beispiel berechnet folgende Funktion die Fakultät rekursiv:</p>
<pre class="brush: js">function factorial(n) {
if ((n === 0) || (n === 1))
return 1;
else
return (n * factorial(n - 1));
}
</pre>
<p>Die Fakultät von 1 bis 5 kann wie folgt berechnet werden:</p>
<pre class="brush: js">var a, b, c, d, e;
a = factorial(1); // a wird der Wert 1 zugewiesen
b = factorial(2); // b wird der Wert 2 zugewiesen
c = factorial(3); // c wird der Wert 6 zugewiesen
d = factorial(4); // d wird der Wert 24 zugewiesen
e = factorial(5); // e wird der Wert 120 zugewiesen
</pre>
<p>Es gibt aber noch weitere Möglichkeiten Funktionen aufzurufen. Oftmals gibt es Fälle, in denen Funktionen dynamisch aufgerufen werden müssen, die Anzahl der Argumente variiert oder der Kontext einer Funktion zur Laufzeit gesetzt werden muss. Das zieht nach sich, dass Funktionen selbst Objekte sind, die Methoden haben (siehe das {{jsxref("Function")}} Objekt). Eine diese Methoden ist die {{jsxref("Function.apply", "apply()")}} Methode, mit der man die oben genannten Aufgaben lösen kann.</p>
<h2 class="deki-transform" id="Scopes_(Gültigkeitsbereiche)_von_Funktionen">Scopes (Gültigkeitsbereiche) von Funktionen</h2>
<p>Variablen, die in einer Funktion definiert werden, können nicht außerhalb der Funktion erreicht werden, weil die Variablen nur im Scope (Gültigkeitbereich) der Funktion definiert sind. Im Gegensatz dazu kann eine Funktion alle Variablen und Funktionen erreichen, die in dem Scope definiert wurden, in dem auch die Funktion definiert wurde. Anders gesagt kann eine Funktion, die im globalen Scope definiert wurde, alle Variablen und Funktionen des globalen Scopes erreichen. Wenn eine Funktion in einer Funktion definiert wird, kann die innere Funktion auf alle Definitionen seiner Elternfunktion und alle Definitionen, auf die die Elternfunktion Zugriff hat, zugreifen.</p>
<pre class="brush: js">// Die folgenden Variablen sind im globalen Scope definiert
var num1 = 20,
num2 = 3,
name = 'Chamahk';
// Diese Funktion ist im globalen Scope definiert
function multiply() {
return num1 * num2;
}
multiply(); // gibt 60 zurück
// Ein Beispiel für verschachtelte Funktionen
function getScore() {
var num1 = 2,
num2 = 3;
function add() {
return name + ' scored ' + (num1 + num2);
}
return add();
}
getScore(); // gibt "Chamahk scored 5" zurück
</pre>
<h2 id="Scope_und_der_Funktionsstack">Scope und der Funktionsstack</h2>
<h3 id="Rekursion">Rekursion</h3>
<p>Eine Funktion kann sich selbst referenzieren und aufrufen. Dabei gibt es drei Möglichkeiten, wie eine Funktion sich selbst referenzieren kann:</p>
<ol>
<li>Der Funktionsname</li>
<li><code><a href="/de/docs/Web/JavaScript/Reference/Functions/arguments/callee">arguments.callee</a></code></li>
<li>Eine im Scope liegende Variable, die auf die Funktion referenziert.</li>
</ol>
<p>Nimmt man zum Beispiel folgende Funktion:</p>
<pre class="brush: js">var foo = function bar() {
// Anweisungen
};
</pre>
<p>Folgende Anweisungen im Körper der Funktion bewirken alle das Gleiche:</p>
<ol>
<li><code>bar()</code></li>
<li><code>arguments.callee()</code></li>
<li><code>foo()</code></li>
</ol>
<p>Eine Funktion, die sich selbst aufruft, wird <em>rekursive Funktion</em> genannt. Rekursion ist dabei vergleichbar mit einer Schleife. Beide führen den selben Quelltext mehrfach aus und beide benötigen eine Bedingung (um eine unendliche Schleife zu vermeiden oder eine unendliche Rekursion zu vermeiden). Das nächste Beispiel zeigt eine Schleife:</p>
<pre class="brush: js">var x = 0;
while (x < 10) { // "x < 10" ist die Schleifenbedingung
// do stuff
x++;
}
</pre>
<p>Diese Schleife kann in eine rekursive Funktion konvertiert werden, die aufgerufen wird:</p>
<pre class="brush: js">function loop(x) {
if (x >= 10) // "x >= 10" ist die Abbruchbedingung (gleich zu "!(x < 10)")
return;
// do stuff
loop(x + 1); // der rekursive Aufruf
}
loop(0);
</pre>
<p>Jedoch können manche Algorithmen nicht in eine <strong>einfache</strong> Schleife umgewandelt werden. Zum Beispiel kann das Abrufen aller Knoten einer Baumstruktur (z. B. <a href="/de/docs/DOM">DOM</a>) einfacher rekursiv realisieren werden:</p>
<pre class="brush: js">function walkTree(node) {
if (node == null) //
return;
// do something with node
for (var i = 0; i < node.childNodes.length; i++) {
walkTree(node.childNodes[i]);
}
}
</pre>
<p>Verglichen mit der Funktion <code>loop</code>, erzeugt hier jeder rekursive Aufruf mehrere weitere rekursive Aufrufe.</p>
<p>Es ist möglich jeden rekursiven Algorithmus in einen nicht rekursiven umzuwandeln, jedoch ist die Logik oftmals sehr viel komplexer und es wird ein zusätzlicher Stack benötigt. Rekursion nutzt ebenfalls einen Stack: den Funktionsstack.</p>
<p>Die Stack-ähnliche Funktionsweise kann in folgendem Beispiel betrachtet werden:</p>
<pre class="brush: js">function foo(i) {
if (i < 0)
return;
console.log('begin:' + i);
foo(i - 1);
console.log('end:' + i);
}
foo(3);
// Output:
// begin: 3
// begin: 2
// begin: 1
// begin: 0
// end: 0
// end: 1
// end: 2
// end: 3</pre>
<h3 id="Verschachtelte_Funktionen_und_Closures">Verschachtelte Funktionen und Closures</h3>
<p>Man kann eine Funktion in eine andere verschachteln. Die verschachtelte (innere) Funktion ist privat innerhalb ihrer Containerfunktion (äußere Funktion). Sie formt auch eine<em> Closure</em>. Eine Closure ist ein Ausdruck, der freie Variablen enthalten kann, (typischerweise eine Funktion) zusammen mit einer Umgebung, welche die diese Variablen einschließt (und damit den Ausdruck <em>abschließt</em>, daher der Name <em>closure</em>).</p>
<p>Weil eine verschachtelte Funktion eine Closure ist, bedeutet das, dass sie die Argumente und Variablen ihrer Containerfunktion vererbt bekommt. Anders gesagt enthält der Scope der inneren Funktion den Scope der äußeren Funktion.</p>
<p>Zusammenfassend:</p>
<ul>
<li>Die innere Funktion kann nur von Anweisungen der äußeren Funktion erreicht werden.</li>
<li>Die innere Funktion formt eine Closure: die innere Funktion kann die Argumente und Variablen der äußeren Funktion benutzen, während die äußere Funktion nicht die Argumente und Variablen der inneren Funktion nutzen kann.</li>
</ul>
<p>Im folgenden Beispiel werden innere Funktionen gezeigt:</p>
<pre class="brush: js">function addSquares(a, b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
a = addSquares(2, 3); // gibt 13 zurück
b = addSquares(3, 4); // gibt 25 zurück
c = addSquares(4, 5); // gibt 41 zurück
</pre>
<p>Weil die innere Funktion eine Closure formt, kann die äußere Funktion aufgerufen werden und Argumente für die innere und äußere Funktion spezifizieren::</p>
<pre class="brush: js">function outside(x) {
function inside(y) {
return x + y;
}
return inside;
}
fn_inside = outside(3); // Man kann sich das folgendermaßen vorstellen
// gib mir eine Funktion, die 3 zu einem Parameter addiert.
result = fn_inside(5); // gibt 8 zurück
result1 = outside(3)(5); // gibt 8 zurück
</pre>
<h3 id="Erhaltung_von_Variablen">Erhaltung von Variablen</h3>
<p>Bemerkenswert ist, dass <code>x</code> erhalten wird, wenn <code>inside</code> zurückgegeben wird. Eine Closure muss alle Argumente und Variablen erhalten, die sie referenziert. Weil jeder Aufruf potenziell verschiedene Argumente benötigt, wird eine neue Closure für jeden Aufruf erstellt. Der Speicher kann nur freigegeben werden, wenn die zurückgegebene <code>inside</code> Funktion nicht mehr erreichbar ist.</p>
<p>Das ist nicht anders mit gespeicherten Referenzen in anderen Objekten, jedoch oftmals weniger deutlich, weil man diese nicht direkt referenziert und nicht inspizieren kann.</p>
<h3 id="Mehrfach_verschachtelte_Funktionen">Mehrfach verschachtelte Funktionen</h3>
<p>Funktionen können mehrfach verschachtelt sein, z. B. eine Funktion (A) enthält eine Funktion (B), die eine Funktion (C) enthält. Beide Funktionen, B und C sind Closures, B kann A erreichen und C kann B erreichen. Zudem kann C auch A erreichen, weil C B erreichen kann und B A erreichen kann. Deswegen kann eine Closure mehrere Scopes enthalten.; sie enthält rekursiv die Scopes der Funktion, die der Container ist. Das wird Scopeverkettung (<em>scope chaining</em>) genannt.</p>
<p>Untersuche das nächste Beispiel:</p>
<pre class="brush: js">function A(x) {
function B(y) {
function C(z) {
console.log(x + y + z);
}
C(3);
}
B(2);
}
A(1); // logs 6 (1 + 2 + 3)
</pre>
<p>In diesem Beispiel benutzt C die Variablen <code>y</code>, von B, und <code>x</code>, von A. Das kann gemacht werden weil:</p>
<ol>
<li><code>B</code> ist eine Closure, die <code>A</code> enthält, z. B. <code>B</code> kann die Argumente und Variablen von <code>A</code> benutzen.</li>
<li><code>C </code>ist ein Closure, die <code>B</code> enthält.</li>
<li>Weil die Closure von B auf A zugreifen kann, kann die Closure von C auf die Argumente und Variablen von A und B zugreifen. Anders gesagt verkettet C den Scope von B und A in dieser Reihenfolge.</li>
</ol>
<p>Das umgekehrte ist nicht möglich. A kann nicht auf C zugreifen, weil A nicht auf die Variablen und Argumente von B zugreifen kann und C eine Variable von B ist. So bleibt C für B privat.</p>
<h3 id="Namenskonflikte">Namenskonflikte</h3>
<p>Wenn zwei Argumente oder Variablen in dem Scope einer Closure mit dem gleichen Namen existieren, gibt es einen Namenskonflikt. Der innerste Scope hat dann Vorrang, was bedeutet, dass der innerste Scope die höchste Priorität hat, während der äußerste Scope die geringste Priorität hat. Das ist wegen der Scopeverkettung. Das erste Glied in der Kette ist der innerste Scope und das letzt Glied ist der äußerste Scope. Dieses ist im folgenden Beispiel zu sehen:</p>
<pre class="brush: js">function outside() {
var x = 10;
function inside(x) {
return x;
}
return inside;
}
result = outside()(20); // gibt 20 statt 10 zurück
</pre>
<p>Der Namenskonflikt tritt beim der Anweisung <code>return x</code> auf und ist zwischen dem Parmeter <code>x</code> von <code>inside</code> und der Variable <code>x</code> von <code> outside</code>. Die Scopekette ist hier {<code>inside</code>, <code>outside</code>, globales Objekt}. Dabei bekommt <code>x</code> von <code>inside</code> eine höhere Priorität als das <code>x</code> von <code>outside</code>. und 20 wird statt der 10 zurückgegeben.</p>
<h2 id="Closures">Closures</h2>
<p>Closures sind eines der mächtigsten Funktionen von JavaScript. JavaScript unterstützt das Verschachteln von Funktionen und erlaubt der inneren Funktionen den vollen Zugriff auf alle definierten Variablen und Funktionen der äußeren Funktion (und alle anderen Variablen und Funktionen die die äußere Funktion erreichen kann). Jedoch hat die äußere Funktion keinen Zugriff auf die Variablen und Funktione, die in der innere Funktion definiert werden. Das unterstützt mehr oder weniger Sicherheit für die Variablen der inneren Funktion. Wenn die innere Funktion Zugriff auf den Scope der äußeren Funktion hat, müssen die Variablen und Funktionen der äußeren Funktion länger leben, als die Ausführungen der inneren Funktion, weil die innere Funktion das Überleben der äußeren Funktion managet. Eine Closure wird erstellt, wenn die innere Funktion irgendwie in einem äußeren Scope der äußeren Funktion erreichbar gemacht wird.</p>
<pre class="brush: js">var pet = function(name) { // Die äußere Funktion definiert eine Variable "name"
var getName = function() {
return name; // Die innere Funktion hat Zugriff auf die "name" Variable der äußeren Funktion
}
return getName; // gibt die innere Funktion zurück
}
myPet = pet('Vivie');
myPet(); // gibt "Vivie" zurück
</pre>
<p>Es kann viel komplexer sein, als der oben gezeigte Quelltext. Ein Objekt enthält Methoden zum verändern von inneren Variablen der äußeren Funktion.</p>
<pre class="brush: js">var createPet = function(name) {
var sex;
return {
setName: function(newName) {
name = newName;
},
getName: function() {
return name;
},
getSex: function() {
return sex;
},
setSex: function(newSex) {
if(typeof newSex === 'string' && (newSex.toLowerCase() === 'male' || newSex.toLowerCase() === 'female')) {
sex = newSex;
}
}
}
}
var pet = createPet('Vivie');
pet.getName(); // Vivie
pet.setName('Oliver');
pet.setSex('male');
pet.getSex(); // male
pet.getName(); // Oliver
</pre>
<p>Im Quelltext oben ist die <code>name</code> Variable der äußeren Funktion in den inneren Funktionen erreichbar und es gibt keine andere Möglichkeit die inneren Variablen zu erreichen, als über die inneren Funktion. Die innere Variable der inneren Funktion fungiert als sicherer Speicher für die äußeren Parameter und Variablen. Sie enthalten permanent und sicher die Daten mit denen die innere Funktion arbeitet. Die Funktion hat niemals eine Variable beschrieben noch hat sie einen Namen.</p>
<pre class="brush: js">var getCode = (function() {
var secureCode = '0]Eal(eh&2'; // Ein Code der nicht von Außerhalb verändert werden soll
return function () {
return secureCode;
};
}());
getCode(); // gibt secureCode zurück.
</pre>
<p>Es gibt aber eine menge von Tücken, die der Einsatz von Closures mit sich bringt. Wenn eine innere Funktion eine Variable definiert, die den gleichen Namen wie eine Variable im äußeren Scope hat, kann die äußere Variable nicht mehr referenziert werden.</p>
<pre class="brush: js">var createPet = function(name) { // Äußere Funktion definiert die Variable "name"
return {
setName: function(name) { // Innere Funktion definiert ebenfalls eine Variable "name"
name = name; // Wie referenziert man die Variable "name" der äußeren Funktion?
}
}
}
</pre>
<h2 id="Einsatz_des_arguments_Objekts">Einsatz des arguments Objekts</h2>
<p>Die Argumente einer Funktion werden in einem Array-ähnlichen Objekt gewartet. In einer Funktion können die Argumente wie folgt adressiert werden:</p>
<pre class="brush: js">arguments[i]
</pre>
<p><code>i</code> ist die Ordnungsnummer des Arguments, beginnend bei null. So ist das erste übergebene Argument einer Funktion <code>arguments[0]</code>. Die Anzahl der übergebenen Argumente ist <code>arguments.length</code>.</p>
<p>Mit dem <code>arguments</code> Objekt kann man eine Funktion mit mehr Agumenten aufrufen als sie formal deklariert wurden. Das ist oft nützlich, wenn man nicht weiß, wie viele Argumente einer Funktion übergeben werden. Mit <code>arguments.length</code> kann die Anzahl der Argumente, die einer Funktion übergeben wurde, ermittelt werden. Über das <code>arguments</code> Objekt können dann alle Argumente gelesen werden.</p>
<p>Zum Beispiel kann es eine Funktion geben, die verschieden viele Strings zusammenfügt. Das einzige formale Argument der Funktion ist das Trennzeichen, welches die Zeichen definiert, die zwischen den Strings eingefügt werden. Im folgenden Quelltext ist die Funktion implementiert:</p>
<pre class="brush: js">function myConcat(separator) {
var result = ''; // initialize list
var i;
// iterate through arguments
for (i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
</pre>
<p>Man kann der Funktion jede Anzahl an Argumenten übergeben und die Funktion fügt die Argumente in einem String zusammen:</p>
<pre class="brush: js">// returns "red, orange, blue, "
myConcat(', ', 'red', 'orange', 'blue');
// returns "elephant; giraffe; lion; cheetah; "
myConcat('; ', 'elephant', 'giraffe', 'lion', 'cheetah');
// returns "sage. basil. oregano. pepper. parsley. "
myConcat('. ', 'sage', 'basil', 'oregano', 'pepper', 'parsley');
</pre>
<div class="note">
<p><strong>Hinweis:</strong> Die <code>arguments</code> Variable ist "Array-ähnlich", aber kein Array. Es ist Array-ähnlich indem es nummerierte Indizes und eine <code>length</code> Eigenschaft hat. Jedoch unterstützt es nicht alle Array-Manipulations-Methoden.</p>
</div>
<p>Siehe im {{jsxref("Function")}} Objekt in den JavaScript Referenzen für mehr Informationen.</p>
<h2 id="Funktionsparameter">Funktionsparameter</h2>
<p>Mit ECMAScript 2015, gibt es zwei neue Arten von Parametern: Default-Parameter und Rest-Parameter.</p>
<h3 id="Default-Parameter">Default-Parameter</h3>
<p>In JavaScript ist der Standardwert eines Parameters <code>undefined</code>. In manchen Situationen ist es sinnvoll den Standardwert auf einen anderen Wert zu setzen. Das ist das Einsatzgebiet von Default-Parametern.</p>
<p>In der Vergangenheit war die Strategie für das Setzen von Standardwerten, dass im Körper der Funktion geprüft wird, ob ein Parameter <code>undefined</code> ist und ihn in diesem Fall neu zu beschreiben. Wenn im folgenden Beispiel kein Argument <code>b</code> übergeben wird, wird dieser <code>undefined</code> sein und die Auswertung von <code>a*b</code> wird <code>NaN</code> sein. Deswegen ist dieser Fall in der zweiten Zeile des Beispiels abgefangen:</p>
<pre class="brush: js">function multiply(a, b) {
b = typeof b !== 'undefined' ? b : 1;
return a * b;
}
multiply(5); // 5
</pre>
<p>Mit Default-Parametern ist die Überprüfung im Körper der Funktion nicht mehr nötig. Jetzt kann man <code>1</code> als Standardwert für <code>b</code> im Funktionskopf angeben:</p>
<pre class="brush: js">function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5</pre>
<p>Für mehr Details, siehe in den Referenzen unter <a href="/de/docs/Web/JavaScript/Reference/Functions/Default_parameters">Default-Parameter</a>.</p>
<h3 id="Rest-Parameter">Rest-Parameter</h3>
<p>Die <a href="/de/docs/Web/JavaScript/Reference/Functions/rest_parameters">Rest-Parameter </a>Syntax ermöglicht er eine unendliche Anzahl von Argumenten als Array zu repräsentieren. Im Beispiel wird der Rest-Parameter eingesetzt um die alle Argumente ab dem zweiten Argument zu sammeln. Danach werden diese mit dem ersten Parameter multipliziert. Dieses Beispiel benutzt Pfeilfunktionen, welche in nächsten Kapitel erklärt werden:</p>
<pre class="brush: js">function multiply(multiplier, ...theArgs) {
return theArgs.map(x => multiplier * x);
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]</pre>
<h2 id="Pfeilfunktionen">Pfeilfunktionen</h2>
<p>Ein <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Pfeilfunktions Ausdruck</a> hat eine kürzere Syntax verglichen mit Funktionsausdrücken und bindet lexikalisch den <code>this</code> Wert. Pfeilfunktionen sind immer anonym. Sie dazu auch den hacks.mozilla.org Blogbeitrag: "<a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">ES6 In Depth: Arrow functions</a>".</p>
<p>Zwei Faktoren haben die Einführung von Pfeilfunktionen beeinflusst: kürzere Funktionen und lexikalisches <code>this</code>.</p>
<h3 id="Kürzere_Funktionen">Kürzere Funktionen</h3>
<p>In manchen funktionalen Patterns sind kurze Funktionen willkommen. Vergleiche:</p>
<pre class="brush: js">var a = [
'Hydrogen',
'Helium',
'Lithium',
'Beryllium'
];
var a2 = a.map(function(s) { return s.length; });
console.log(a2); // logs [8, 6, 7, 9]
var a3 = a.map( s => s.length );
console.log(a3); // logs [8, 6, 7, 9]
</pre>
<h3 id="Lexikalisches_this">Lexikalisches <code>this</code></h3>
<p>Bis es Pfeilfunktionen gab, hat jede neue Funktion sein eigenen <a href="/de/docs/Web/JavaScript/Reference/Operators/this">this</a> Wert definiert (ein neues Objekt in Fällen eines Konstruktors, undefined in Funktionsaufrufen im strict mode, das Kontextobjekt, wenn eine Funktion als Objektmethode aufgerufen wird, etc.). Das ist lästig mit objektorientierten Programmierstilen.</p>
<pre class="brush: js">function Person() {
// The Person() constructor defines `<code>this`</code> as itself.
this.age = 0;
setInterval(function growUp() {
// In nonstrict mode, the growUp() function defines `this`
// as the global object, which is different from the `this`
// defined by the Person() constructor.
this.age++;
}, 1000);
}
var p = new Person();</pre>
<p>In ECMAScript 3/5, wurde dieses Problem behoben, indem der Wert der Variablen <code>this</code> in einer weiteren Variablen gespeichert wird.</p>
<pre class="brush: js">function Person() {
var self = this; // Some choose `that` instead of `self`.
// Choose one and be consistent.
self.age = 0;
setInterval(function growUp() {
// The callback refers to the `self` variable of which
// the value is the expected object.
self.age++;
}, 1000);
}</pre>
<p>Alternativ kann eine <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">gebundene Funktion</a> erstellt werden, so dass der Wert für <code>this</code> mit übergeben werden kann.</p>
<p>Pfeilfunktionen nutzen den <code>this</code> Wert des umschließenden Kontextes, so dass der folgende Quelltext wie erwartet funktioniert:</p>
<pre class="brush: js">function Person() {
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();</pre>
<h2 id="Vordefinierte_Funktionen">Vordefinierte Funktionen</h2>
<p>JavaScript hat einige eingebaute Funktionen:</p>
<dl>
<dt>{{jsxref("Global_Objects/eval", "eval()")}}</dt>
<dd>
<p>Die <code><strong>eval()</strong></code> Methode wertet JavaScript Quelltext repräsentiert als String aus.</p>
</dd>
<dt>{{jsxref("Global_Objects/uneval", "uneval()")}} {{non-standard_inline}}</dt>
<dd>
<p>Die <code><strong>uneval()</strong></code> Methode erstellt einen String der Quelltext eines {{jsxref("Object")}}s repräsentiert.</p>
</dd>
<dt>{{jsxref("Global_Objects/isFinite", "isFinite()")}}</dt>
<dd>
<p>Die globale <code><strong>isFinite()</strong></code> Funktion ob ein übergebener Wert endlich ist. Der übergebene Wert wird, wenn es nötig ist, zu einer Zahl konvertiert.</p>
</dd>
<dt>{{jsxref("Global_Objects/isNaN", "isNaN()")}}</dt>
<dd>Die <code><strong>isNaN()</strong></code> Funktion überprüft, ob ein Wert {{jsxref("Global_Objects/NaN", "NaN")}} ist oder nicht. Hinweis: Wegen einigen Zwängen innerhalb der <code>isNaN</code> Funktion gibt es <a href="/de/docs/Web/JavaScript/Reference/Global_Objects/isNaN#Beschreibung">interessante Regeln</a>; alternativ kann auch die in ECMAScript 2015 definierte Funktion Funktion {{jsxref("Number.isNaN()")}} oder der Operator <code><a href="/de/docs/Web/JavaScript/Reference/Operators/typeof">typeof</a></code> verwendet werden, um einen {{jsxref("Global_Objects/NaN", "NaN")}} Wert zu erkennen.</dd>
<dt>{{jsxref("Global_Objects/parseFloat", "parseFloat()")}}</dt>
<dd>
<p>Doe <code><strong>parseFloat()</strong></code> Funktion liest einen String als Argument ein und gibt eine Gleitkommazahl zurück.</p>
</dd>
<dt>{{jsxref("Global_Objects/parseInt", "parseInt()")}}</dt>
<dd>
<p>Die <code><strong>parseInt()</strong></code> Funktion liest einen String als Argument ein und gibt eine ganze Zahl der Spezifizierten Basis zurück (die Basis ist in der Mathematik das Zahlensystem).</p>
</dd>
<dt>{{jsxref("Global_Objects/decodeURI", "decodeURI()")}}</dt>
<dd>
<p>Die <code><strong>decodeURI()</strong></code> Methode decodiert einen Uniform Resource Identifier (URI), der vorher mit der {{jsxref("Global_Objects/encodeURI", "encodeURI")}} Funktion order einer ähnlichen Funktion erstellt wurde.</p>
</dd>
<dt>{{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent()")}}</dt>
<dd>
<p>Die <code><strong>decodeURIComponent()</strong></code> Methode decodiert eine Uniform Resource Identifier (URI) Komponente, die vorher mit der {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} Funktion oder einer ähnlichen Funktion erstellt wurde.</p>
</dd>
<dt>{{jsxref("Global_Objects/encodeURI", "encodeURI()")}}</dt>
<dd>
<p>Die <code><strong>encodeURI()</strong></code> Methode codiert einen Uniform Resource Identifier (URI), indem jedes besondere Zeilen durch eine Sequenz aus zwei drei oder vier Zeichen escaped wird. Dieses Sequenzen Repräsentieren die UTF-8 Darstellung der Zeichen (wird nur vier escape Sequenzen von Zeichen zu zwei zwei Platzhalterzeichen umwandeln)</p>
</dd>
<dt>{{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}}</dt>
<dd>
<p>Die <code><strong>encodeURIComponent()</strong></code> Methode codiert eine Uniform Resource Identifier (URI) Komponente, indem jedes besondere Zeilen durch eine Sequenz aus zwei drei oder vier Zeichen escaped wird. Dieses Sequenzen Repräsentieren die UTF-8 Darstellung der Zeichen (wird nur vier escape Sequenzen von Zeichen zu zwei zwei Platzhalterzeichen umwandeln)</p>
</dd>
<dt>{{jsxref("Global_Objects/escape", "escape()")}} {{deprecated_inline}}</dt>
<dd>
<p>Die veraltete <code><strong>escape()</strong></code> Methode berechnet einen neuen String indem manche Zeichen durch Hexadezimalsequenzen ersetzt werden. Man sollte {{jsxref("Global_Objects/encodeURI", "encodeURI")}} oder {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} stattdessen benutzen.</p>
</dd>
<dt>{{jsxref("Global_Objects/unescape", "unescape()")}} {{deprecated_inline}}</dt>
<dd>
<p>Die veraltete <code><strong>unescape()</strong></code> Methode berechnet einen neuen String indem Hexadezimalsequenzen durch die repräsentierenden Zeichen ersetzt werden. Die Hexadezimalsequenzen können von Funktionen wie {{jsxref("Global_Objects/escape", "escape")}} eingeführt werden. Weil <code>unescape()</code> veraltet ist, sollte man stattdessen die Funktion {{jsxref("Global_Objects/decodeURI", "decodeURI()")}} oder {{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent")}} benutzen.</p>
</dd>
</dl>
<p>{{PreviousNext("Web/JavaScript/Guide/Schleifen_und_Iterationen", "Web/JavaScript/Guide/Ausdruecke_und_Operatoren")}}</p>
|