diff options
Diffstat (limited to 'files/de/web/javascript/reference/functions/pfeilfunktionen/index.html')
-rw-r--r-- | files/de/web/javascript/reference/functions/pfeilfunktionen/index.html | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/files/de/web/javascript/reference/functions/pfeilfunktionen/index.html b/files/de/web/javascript/reference/functions/pfeilfunktionen/index.html new file mode 100644 index 0000000000..a29b5ea3cf --- /dev/null +++ b/files/de/web/javascript/reference/functions/pfeilfunktionen/index.html @@ -0,0 +1,360 @@ +--- +title: Pfeilfunktionen +slug: Web/JavaScript/Reference/Functions/Pfeilfunktionen +tags: + - ECMAScript 2015 + - Functions + - Intermediate + - JavaScript + - Reference +translation_of: Web/JavaScript/Reference/Functions/Arrow_functions +--- +<div>{{jsSidebar("Functions")}}</div> + +<p>Der <strong>Ausdruck einer Pfeilfunktion</strong> hat eine kürzere Syntax als ein <a href="/de/docs/Web/JavaScript/Reference/Operators/function">Funktionsausdruck</a> und hat kein eigenes <code><a href="/de/docs/Web/JavaScript/Reference/Operators/this">this</a></code>, <a href="/de/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>, <a href="/de/docs/Web/JavaScript/Reference/Operators/super">super</a>, oder <a href="/de/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a>. Solche Funktionsausdrücke sind am besten für Funktionen, die nicht als Methode genutzt werden, geeignet und können nicht als Konstruktoren verwendet werden.</p> + +<div>{{EmbedInteractiveExample("pages/js/functions-arrow.html")}}</div> + +<h2 id="Syntax">Syntax</h2> + +<h3 id="Basis_Syntax">Basis Syntax</h3> + +<pre class="syntaxbox">(param1, param2, …, paramN) => { statements } +(param1, param2, …, paramN) => expression +// gleich zu: => { return expression; } + +// Klammern sind optional, wenn nur ein Parametername vorhanden ist: +(singleParam) => { statements } +singleParam => { statements } + +// Die Parameterliste für eine parameterlose Funktion muss mit einem Klammernpaar geschrieben werden +() => { statements } +</pre> + +<h3 id="Fortgeschrittene_Syntax">Fortgeschrittene Syntax</h3> + +<pre class="syntaxbox">// Der Body kann eingeklammert werden, um ein Objektliteral Ausdruck zurück zu geben: +params => ({foo: bar}) + +// <a href="/de/docs/Web/JavaScript/Reference/Functions/rest_parameters">Rest Parameter</a> und <a href="/de/docs/Web/JavaScript/Reference/Functions/Default_parameters">Default Parameter</a> werden unterstützt +(param1, param2, ...rest) => { statements } +(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { +statements } + +// <a href="/de/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">Destrukturierung</a> in der Parameterliste ist ebenfalls unterstützt +var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; +f(); // 6 +</pre> + +<h2 id="Beschreibung">Beschreibung</h2> + +<p>Siehe auch <a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a>.</p> + +<p>Zwei Faktoren haben die Einführung von Pfeilfunktionen beeinflusst: kürzere Funktionen und dass <code>this</code> nicht gebunden ist.</p> + +<h3 id="Kürzere_Funktionen">Kürzere Funktionen</h3> + +<pre class="brush: js">var elements = [ + "Hydrogen", + "Helium", + "Lithium", + "Beryllium" +]; + +elements.map(function(element) { + return element.length +}); // [8, 6, 7, 9] + +elements.map(element => { + return element.length +}); // [8, 6, 7, 9] + +elements.map(({length}) => length); // [8, 6, 7, 9]</pre> + +<h3 id="Keine_Bindung_von_this">Keine Bindung von <code>this</code></h3> + +<p>Vor (der Einführung von) Pfeilfunktionen definierte jede Funktion ihren eigenen <code><a href="/de/docs/Web/JavaScript/Reference/Operators/this">this</a></code>-Wert (d.h. ein neues Objekt im Falle eines Konstruktors; in <a href="/de/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a> Funktionsaufrufen nicht definiert; bzw. das kontextuelle Objekt, wenn die Funktion als eine "Objekt-Methode" aufgerufen wurde, usw.). Dies stellte sich innerhalb eines objektorientierten Programmierstils als lästig heraus.</p> + +<pre class="brush: js">function Person() { + // Der Person() Konstruktor definiert `this` als Instanz von sich selbst. + this.age = 0; + + setInterval(function growUp() { + // Im nicht Strict Modus, definiert die growUp() Funktion `this` + // als das globale Objekt (weil das der Ort ist, an dem growUp() ausgeführt wird), + // das sich von dem `this`, welches vom Person() Konstruktor definiert wurde unterscheidet. + this.age++; + }, 1000); +} + +var p = new Person();</pre> + +<p>In ECMAScript 3/5 konnte dies durch Zuweisung des Wertes von <code>this</code> an eine Variable, welche umschlossen werden konnte, behoben werden.</p> + +<pre class="brush: js">function Person() { + var that = this; + that.age = 0; + + setInterval(function growUp() { + // Der Rückruf bezieht sich auf jene `that`-Variable, + // deren Wert das zu erwartende Objekt ist. + that.age++; + }, 1000); +}</pre> + +<p>Alternativ könnte eine <a href="/de/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">gebundene Funktion</a> erstellt werden, sodass der passende <code>this</code>-Wert an die <code>growUp()</code>-Funktion übergeben würde.</p> + +<p>Eine Pfeilfunktion erstellt keinen eigenen <code>this</code> Kontext, wodurch <code>this</code> die ursprüngliche Bedeutung des umschließenden Kontextes trägt. Somit funktioniert der folgende Code wie erwartet.</p> + +<pre class="brush: js">function Person(){ + this.age = 0; + + setInterval(() => { + this.age++; // |this| bezieht sich entsprechend auf das Person-Objekt + }, 1000); +} + +var p = new Person();</pre> + +<h4 id="Zusammenhang_mit_dem_Strict_Mode">Zusammenhang mit dem Strict Mode</h4> + +<p>Vorausgesetzt, dass <code>this</code> aus dem umschließenden lexikalischen Kontext kommt, werden <a href="/de/docs/Web/JavaScript/Reference/Strict_mode">Strict Mode</a> Regeln bezüglich <code>this</code> einfach ignoriert.</p> + +<pre class="brush: js">var f = () => {'use strict'; return this}; +f() === window; // oder das globale Objekt</pre> + +<p>Die restlichen strict mode Regeln verhalten sich normal.</p> + +<h4 id="Aufruf_durch_call_oder_apply">Aufruf durch call oder apply</h4> + +<p>Da <code>this</code><em> </em>in Pfeilfunktionen nicht gebunden ist, können <code>call()</code><em> </em>oder <code>apply()</code> Methoden nur Argumente übergeben; <code>this</code> wird ignoriert:</p> + +<pre class="brush: js">var adder = { + base : 1, + + add : function(a) { + var f = v => v + this.base; + return f(a); + }, + + addThruCall: function(a) { + var f = v => v + this.base; + var b = { + base : 2 + }; + + return f.call(b, a); + } +}; + +console.log(adder.add(1)); // Dies würde 2 ausgeben +console.log(adder.addThruCall(1)); // Dies würde nach wie vor 2 ausgeben</pre> + +<h3 id="Keine_Bindung_von_Argumenten">Keine Bindung von Argumenten</h3> + +<p>Pfeilfunktionen haben kein eigenes <a href="/de/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code> Objekt</a>. Somit ist <code>arguments</code> einfach eine Referenz auf den Namen innerhalb des umschließenden Geltungsbereichs (scope).</p> + +<pre class="brush: js">var arguments = [1, 2, 3]; +var arr = () => arguments[0]; + +arr(); // 1 + +function foo(n) { + var f = () => arguments[0] + n; // implizite Argumenten-Bindung von <em>foo</em> + return f(); +} + +foo(1); // 2</pre> + +<p>In den meisten Fällen sind <a href="/de/docs/Web/JavaScript/Reference/Functions/rest_parameters">Rest Parameters</a> eine gute Alternative zum Einsatz des <code>arguments</code> Objektes:</p> + +<pre class="brush: js">function foo(n) { + var f = (...args) => args[0] + n; + return f(10); +} + +foo(1); // 11</pre> + +<h3 id="Pfeilfunktionen_als_Methoden">Pfeilfunktionen als Methoden</h3> + +<p>Wie angegeben, sind Ausdrücke von Pfeilfunktionen am besten geeignet für nicht-methodische Funktionen. Man sehe, was geschieht, wenn versucht wird, sie als Methoden zu verwenden.</p> + +<pre class="brush: js">'use strict'; + +var obj = { + i: 10, + b: () => console.log(this.i, this), + c: function() { + console.log( this.i, this) + } +} +obj.b(); // gibt undefined, Window {...} aus (oder das globale Objekt) +obj.c(); // gibt 10, Object {...} aus</pre> + +<p>Pfeilfunktionen definieren (binden sozusagen) kein eigenes <code>this</code>. Ein anderes Beispiel, das {{jsxref("Object.defineProperty()")}} betrifft:</p> + +<pre class="brush: js">'use strict'; + +var obj = { + a: 10 +}; + +Object.defineProperty(obj, "b", { + get: () => { + console.log(this.a, typeof this.a, this); + return this.a+10; // stellt das globale Objekt 'Window' dar, 'this.a' gibt daher 'undefined' zurück + } +}); +</pre> + +<h3 id="Verwendung_des_new_Operators">Verwendung des <code>new</code> Operators</h3> + +<p>Pfeilfunktionen können nicht als Konstruktoren verwendet werden. Sie führen zu einem Fehler, wenn auf ihnen ein <code>new</code> angewendet wird.</p> + +<pre class="brush: js">var Foo = () => {}; +var foo = new Foo(); // TypeError: Foo is not a constructor +</pre> + +<h3 id="Einsatz_der_prototype_Eigenschaft">Einsatz der <code>prototype</code> Eigenschaft</h3> + +<p>Pfeilfunktionen haben keine <code>prototype</code> Eigenschaft.</p> + +<pre class="brush: js">var Foo = () => {}; +console.log(Foo.prototype); // undefined +</pre> + +<h3 id="Verwendung_des_Schlüsselwortes_yield">Verwendung des Schlüsselwortes <code>yield</code></h3> + +<p>Das <code><a href="/de/docs/Web/JavaScript/Reference/Operators/yield">yield</a></code>-Schlüsselwort sollte im Körper einer Pfeilfunktion nicht verwendet werden (außer wenn dies innerhalb von darin weiter verschachtelten Funktionen erlaubt ist). Als Folge können Pfeilfunktionen nicht als Generatoren verwendet werden.</p> + +<h2 id="Funktionskörper">Funktionskörper</h2> + +<p>Pfeilfunktionen können entweder einen "knappen" oder einen gewöhnlichen "Blockkörper" haben.</p> + +<p>In einem knappen Körper ist lediglich ein Ausdruck nötig und eine implizite Rückgabe wird angehängt. In einem Blockkörper muss eine explizite Rückgabe-Anweisung verwendet werden.</p> + +<pre class="brush: js">var func = x => x * x; +// knappe Syntax, implizierte Rückgabe + +var func = (x, y) => { return x + y; }; +// mit Blockkörper, explizite Rückgabe wird benötigt +</pre> + +<h2 id="Rückgabe_von_Objekt-Literalen">Rückgabe von Objekt-Literalen</h2> + +<p>Man bedenke, dass die Rückgabe von Objekt-Literalen unter Verwendung der knappen Syntax <code>params => {object:literal}</code> nicht so ausgeführt wird, wie man es erwarten würde:</p> + +<pre class="brush: js">var func = () => { foo: 1 }; +// Der Aufruf von func() gibt undefined zurück! + +var func = () => { foo: function() {} }; +// SyntaxError: function-Anweisung erfordert einen Namen</pre> + +<p>Der Grund dafür ist, dass der Code in geschweiften Klammern ({}) als eine Sequenz von Anweisungen übersetzt wird (d.h. foo wird als Bezeichner behandelt und nicht als Schlüssel eines Objekt-Literals).</p> + +<p>Man bedenke, das Objekt-Literal in Klammern zu setzen:</p> + +<pre class="brush: js">var func = () => ({ foo: 1 });</pre> + +<h2 id="Zeilenumbruch">Zeilenumbruch</h2> + +<p>Pfeilfunktionen können keinen Zeilenumbruch zwischen Parametern und dem Pfeil haben.</p> + +<pre class="brush: js">var func = () + => 1; +// SyntaxError: Ausdruck erwartet, '=>' erhalten</pre> + +<h2 id="Übersetzungsreihenfolge">Übersetzungsreihenfolge</h2> + +<p>Der Pfeil innerhalb einer Pfeilfunktion ist kein Operator. Allerdings haben Pfeilfunktionen im Vergleich zu gewöhnlichen Funktionen besondere Übersetzungsregeln, welche mit der Priorität von Operatoren (<a href="/de/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">operator precedence</a>) anders interagieren.</p> + +<pre class="brush: js">let callback; + +callback = callback || function() {}; // ok + +callback = callback || () => {}; +// SyntaxError: invalid arrow-function arguments + +callback = callback || (() => {}); // ok +</pre> + +<h2 id="Weitere_Beispiele">Weitere Beispiele</h2> + +<pre class="brush: js">// Eine leere Pfeilfunktion gibt undefined zurück +let empty = () => {}; + +(() => "foobar")() +// Gibt "foobar" zurück +// (Das ist eine Immediately Invoked Function Expression +// siehe IIFE im Glossar + +var simple = a => a > 15 ? 15 : a; +simple(16); // 15 +simple(10); // 10 + +let max = (a, b) => a > b ? a : b; + +// Einfaches filtering, mapping, ... von Arrays + +var arr = [5, 6, 13, 0, 1, 18, 23]; + +var sum = arr.reduce((a, b) => a + b); +// 66 + +var even = arr.filter(v => v % 2 == 0); +// [6, 0, 18] + +var double = arr.map(v => v * 2); +// [10, 12, 26, 0, 2, 36, 46] + +// Weitere knappe Zusicherungsketten (promise chains) +promise.then(a => { + // ... +}).then(b => { + // ... +}); + +// Parameterlose Pfeilfunktionen, welche visuell einfacher zu verstehen sind +setTimeout( _ => { + console.log("I happen sooner"); + setTimeout( _ => { + // deeper code + console.log("I happen later"); + }, 1); +}, 1);</pre> + +<h2 id="Spezifikationen">Spezifikationen</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Spezifikation</th> + <th scope="col">Status</th> + <th scope="col">Kommentar</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initiale Definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Browserkompatibilität">Browserkompatibilität</h2> + +<div> + + +<p>{{Compat("javascript.functions.arrow_functions")}}</p> +</div> + +<h2 id="Siehe_auch">Siehe auch</h2> + +<ul> + <li><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a></li> +</ul> |