diff options
Diffstat (limited to 'files/de/web/javascript/guide/functions/index.html')
-rw-r--r-- | files/de/web/javascript/guide/functions/index.html | 658 |
1 files changed, 658 insertions, 0 deletions
diff --git a/files/de/web/javascript/guide/functions/index.html b/files/de/web/javascript/guide/functions/index.html new file mode 100644 index 0000000000..4712c55d02 --- /dev/null +++ b/files/de/web/javascript/guide/functions/index.html @@ -0,0 +1,658 @@ +--- +title: Funktionen +slug: Web/JavaScript/Guide/Functions +tags: + - Beginner + - Functions + - Guide + - JavaScript + - l10n:priority +translation_of: Web/JavaScript/Guide/Functions +original_slug: Web/JavaScript/Guide/Funktionen +--- +<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> |