Diese Übersetzung ist unvollständig. Bitte helfen Sie, diesen Artikel aus dem Englischen zu übersetzen.

Der Ausdruck einer Pfeilfunktion hat im Vergleich zu (allgemeinen) Funktionsausdrücken eine kürzere Syntax und bindet kein eigenes thisargumentssuper, oder new.target. Pfeilfunktionen sind immer anonym. Solche Funktionsausdrücke sind am besten für nicht-methodische Funktionen geeignet und können nicht als Konstruktoren verwendet werden.

Syntax

Basis Syntax

(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// äquivalent zu: (param1, param2, …, paramN) => { return expression; }

// Bei nur einem Parameter sind Klammern optional:
(singleParam) => { statements }
singleParam => { statements }

// Eine parameterlose Funktion erfordert Klammern:
() => { statements }
() => expression // equivalent to: () => { return expression; }

Fortgeschrittene Syntax

// Parenthesize the body to return an object literal expression:
params => ({foo: bar})

// Rest parameters and default parameters are supported
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }

// Destructuring within the parameter list is also supported
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6

Detailierte Beispiele zur Syntax sind hier zu finden.

Beschreibung

Siehe auch "ES6 In Depth: Arrow functions" on hacks.mozilla.org.

Zwei Faktoren haben die Einführung von Pfeilfunktionen beeinflusst: kürzere Funktionen und dass this nicht gebunden ist.

Kürzere Funktionen

In einigen funktionalen Mustern sind kürzere Funktionen willkommen. Vergleiche:

var a = [
  "Hydrogen",
  "Helium",
  "Lithium",
  "Beryllium"
];

var a2 = a.map(function(s){ return s.length });

var a3 = a.map( s => s.length );

Keine Bindung von this

Vor (der Einführung von) Pfeilfunktionen definierte jede Funktion ihren eigenen this-Wert (d.h. ein neues Objekt im Falle eines Konstruktors; in strict mode Funktionsaufrufen nicht definiert; bzw. das kontextuelle Objekt, wenn die Funktion als eine "Objekt-Methode" aufgerufen wurde, usw.). Dies stellte sich innerhalb eines objekt-orientierten Programmierstils als lästig heraus.

function Person() {
  // Der Person() Konstruktor definiert `this` als Instanz von sich selbst.
  this.age = 0;

  setInterval(function growUp() {
    // Im non-strict mode, definiert die growUp() Funktion `this` 
    // als das globale Objekt, das sich jenem `this` unterscheidet, 
    // welches vom Person() Konstruktor definiert wurde.
    this.age++;
  }, 1000);
}

var p = new Person();

In ECMAScript 3/5 konnte dies durch Zuweisung des Wertes von this an eine Variable, welche umschlossen werden konnte, behoben werden.

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);
}

Alternativ könnte eine gebundene Funktion erstellt werden, sodass der passende this-Wert an die growUp()-Funktion übergeben würde.

Eine Pfeilfunktion erstellt keinen eigenen this Kontext, wodurch this die ursprüngliche Bedeutung des umschließenden Kontextes trägt. Somit funktioniert der folgende Code wie erwartet.

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| bezieht sich entsprechend auf das person-Objekt
  }, 1000);
}

var p = new Person();

Zusammenhang mit dem strict mode

Vorausgesetzt, dass this lexical ist, werden strict mode Regeln bezüglich this einfach ignoriert.

var f = () => {'use strict'; return this};
f() === window; // oder das globale Objekt

Die restlichen strict mode Regeln verhalten sich normal.

Aufruf durch call oder apply

Da this in Pfeilfunktionen nicht gebunden ist, können call() oder apply() Methoden nur Argumente übergeben; this wird ignoriert:

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

Keine Bindung von Argumenten

Pfeilfunktionen binden kein arguments object. Somit ist arguments einfach eine Referenz auf den Namen innerhalb des umschließenden Geltungsbereichs (scope).

var arguments = 42;
var arr = () => arguments;

arr(); // 42

function foo() {
  var f = (i) => arguments[0]+i; // implizite Argumenten-Bindung von foo
  return f(2);
}

foo(1); // 3

Pfeilfunktionen haben kein eigenes arguments-Objekt, jedoch ist die variable Parameteranzahl (rest parameters) in den meisten Fällen eine gute Alternative:

function foo() { 
  var f = (...args) => args[0]; 
  return f(2); 
}

foo(1); // 2

Pfeilfunktionen als Methoden

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.

'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
obj.c(); // gibt `10, Object {...}` aus

Pfeilfunktionen definieren (binden sozusagen) kein eigenes this. Ein anderes Beispiel, das Object.defineProperty() betrifft:

'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
  }
});

Verwendung des new Operators

Pfeilfunktionen können nicht als Konstruktoren verwendet werden. Sie rufen einen Fehler hervor, wenn auf sie ein new angwandt wird.

Verwendung des Schlüsselwortes yield

Das yield-Schlüsselwort sollte im Rumpf 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.

Funktionsrumpf

Pfeilfunktionen können entweder einen "knappen" oder einen gewöhnlichen "Block-Rumpf" haben.

In einem knappen Rumpf ist lediglich ein Ausdruck nötig und eine implizite Rückgabe wird angehängt. In einem Block-Rumpf muss eine explizite Rückgabe-Anweisung verwendet werden.

var func = x => x * x;                  // knappe Syntax, implizierte Rückgabe
var func = (x, y) => { return x + y; }; // mit Block-Rumpf, explizite Rückgabe wird benötigt

Rückgabe von Objekt-Literalen

Man bedenke, dass die Rückgabe von Objekt-Literalen unter Verwendung der knappen Syntax params => {object:literal} nicht so ausgeführt wird, wie man es erwarten würde:

var func = () => {  foo: 1  };               // Der Aufruf von func() gibt undefined zurück!
var func = () => {  foo: function() {}  };   // SyntaxError: function-Anweisung erfordert einen Namen

Dies, weil der Code innerhalb der geschweiften Klammern ({}) als eine Sequenz von Anweisungen übersetzt wird (d.h. foo wird als Bezeichner behandelt und nicht als Schlüssel eines Objekt-Literals).

Man bedenke, das Objekt-Literal in Klammern zu setzen:

var func = () => ({ foo: 1 });

Zeilenumbruch

Pfeilfunktionen können keinen Zeilenumbruch zwischen Parametern und dem Pfeil haben.

var func = ()
           => 1; // SyntaxError: Ausdruck erwartet, '=>' erhalten

Übersetzungsreihenfolge

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 (operator precedence) anders interagieren.

let callback;

callback = callback || function() {}; // ok
callback = callback || () => {};      // SyntaxError: ungültige Pfeilfunktions-Argumente
callback = callback || (() => {});    // ok

Weitere Beispiele

// Eine leere Pfeilfunktion gibt undefined zurück
let empty = () => {};

(() => "foobar")() // IIFE, returns "foobar" 

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 => {
   // ...
});

// Paramterlose Pfeilfunktionen, welche visuell einfacher zu verstehen sind
setTimeout( _ => {
  console.log("I happen sooner");
  setTimeout( _ => {
    // deeper code
    console.log("I happen later");
  }, 1);
}, 1);  

 

 

 

Specificationen

Spezifikation Status Kommentar
ECMAScript 2015 (6th Edition, ECMA-262)
Die Definition von 'Arrow Function Definitions' in dieser Spezifikation.
Standard Initiale Definition.
ECMAScript Latest Draft (ECMA-262)
Die Definition von 'Arrow Function Definitions' in dieser Spezifikation.
Lebender Standard  

Browserkompatibilität

Feature Chrome Firefox (Gecko) Edge IE Opera Safari
Basic support 45.0 22.0 (22.0) (Ja)

Nicht unterstützt

32 10.0
Feature Android Android Webview Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
Basic support Nicht unterstützt 45.0 22.0 (22.0) Nicht unterstützt Nicht unterstützt 10.0 45.0

Firefox-spezifische Anmerkungen

  • Durch die initiale Implementierung von Pfeilfunktionen in Firefox wurden diese automatisch als strict gesetzt. Dies hat sich gemäß Firefox 24 geändert. Die Verwendung von "use strict"; ist nun erforderlich.
  • Pfeilfunktionen unterscheiden sich semantisch vom Nicht-Standard expression closures, welches in Firefox 3 hinzugefügt wurde (für Details: JavaScript 1.8), da this von expression closures  lexikalisch nicht gebunden wird.
  • Vor Firefox 39 war ein Zeilenumbruch (\n) nach Argumenten einer Pfeilfunktion fälschlicherweise erlaubt. Dies wurde behoben, um den ES6 Spezifikationen gerecht zu werden und damit Code wie () \n => {} in dieser und folgenden Versionen keinen SyntaxError wirft.

Siehe auch

Schlagwörter des Dokuments und Mitwirkende

 Mitwirkende an dieser Seite: Eiknheimer, GuidoSchweizer, mhash17
 Zuletzt aktualisiert von: Eiknheimer,