Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

Pfeilfunktion-Ausdrücke

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.

Ein Pfeilfunktion-Ausdruck ist eine kompakte Alternative zu einem herkömmlichen Funktionsausdruck, mit einigen semantischen Unterschieden und bewussten Einschränkungen bei der Verwendung:

  • Pfeilfunktionen haben keine eigenen Bindings für this, arguments oder super und sollten nicht als Methoden verwendet werden.
  • Pfeilfunktionen können nicht als Konstruktoren verwendet werden. Ein Aufruf mit new löst einen TypeError aus. Sie haben auch keinen Zugriff auf das Schlüsselwort new.target.
  • Pfeilfunktionen können innerhalb ihres Körpers nicht yield verwenden und können nicht als Generatorfunktionen erstellt werden.

Probieren Sie es aus

const materials = ["Hydrogen", "Helium", "Lithium", "Beryllium"];

console.log(materials.map((material) => material.length));
// Expected output: Array [8, 6, 7, 9]

Syntax

js
() => expression

param => expression

(param) => expression

(param1, paramN) => expression

() => {
  statements
}

param => {
  statements
}

(param1, paramN) => {
  statements
}

Rest-Parameter, Standardparameter und Destrukturierung innerhalb der Parameter werden unterstützt und erfordern immer Klammern:

js
(a, b, ...r) => expression
(a = 400, b = 20, c) => expression
([a, b] = [10, 20]) => expression
({ a, b } = { a: 10, b: 20 }) => expression

Pfeilfunktionen können async sein, indem man den Ausdruck mit dem async-Schlüsselwort versieht.

js
async param => expression
async (param1, param2, ...paramN) => {
  statements
}

Beschreibung

Lassen Sie uns eine traditionelle anonyme Funktion Schritt für Schritt auf die einfachste Pfeilfunktion reduzieren. Jeder Schritt auf dem Weg ist eine gültige Pfeilfunktion.

Hinweis: Traditionelle Funktionsausdrücke und Pfeilfunktionen unterscheiden sich nicht nur in ihrer Syntax. Wir werden ihre Verhaltensunterschiede in den nächsten Abschnitten detaillierter vorstellen.

js
// Traditional anonymous function
(function (a) {
  return a + 100;
});

// 1. Remove the word "function" and place arrow between the argument and opening body brace
(a) => {
  return a + 100;
};

// 2. Remove the body braces and word "return" — the return is implied.
(a) => a + 100;

// 3. Remove the parameter parentheses
a => a + 100;

Im obigen Beispiel können sowohl die Klammern um den Parameter als auch die geschweiften Klammern um den Funktionskörper weggelassen werden. Dies ist jedoch nur in bestimmten Fällen möglich.

Die Klammern können nur weggelassen werden, wenn die Funktion einen einzelnen einfachen Parameter hat. Bei mehreren Parametern, keinen Parametern oder Standard-, desktrukturierten oder Rest-Parametern sind die Klammern um die Parameterliste erforderlich.

js
// Traditional anonymous function
(function (a, b) {
  return a + b + 100;
});

// Arrow function
(a, b) => a + b + 100;

const a = 4;
const b = 2;

// Traditional anonymous function (no parameters)
(function () {
  return a + b + 100;
});

// Arrow function (no parameters)
() => a + b + 100;

Die geschweiften Klammern können nur weggelassen werden, wenn die Funktion direkt einen Ausdruck zurückgibt. Wenn der Körper Anweisungen enthält, sind die Klammern erforderlich. In diesem Fall müssen Rückgabewerte ausdrücklich mit dem return-Schlüsselwort angegeben werden. Pfeilfunktionen können nicht erraten, was oder wann Sie zurückgeben möchten.

js
// Traditional anonymous function
(function (a, b) {
  const chuck = 42;
  return a + b + chuck;
});

// Arrow function
(a, b) => {
  const chuck = 42;
  return a + b + chuck;
};

Pfeilfunktionen sind von Natur aus nicht mit einem Namen verbunden. Wenn die Pfeilfunktion sich selbst aufrufen muss, verwenden Sie stattdessen einen benannten Funktionsausdruck. Sie können die Pfeilfunktion auch einer Variablen zuweisen, sodass Sie über diese Variable darauf zugreifen können.

js
// Traditional Function
function bob(a) {
  return a + 100;
}

// Arrow Function
const bob2 = (a) => a + 100;

Funktionskörper

Pfeilfunktionen können entweder einen Ausdruckskörper oder einen üblichen Blockkörper haben.

In einem Ausdruckskörper wird nur ein einzelner Ausdruck angegeben, der zum impliziten Rückgabewert wird. Der Blockkörper ist analog zu traditionellen Funktionskörpern, in denen Rückgabewerte ausdrücklich mit dem return-Schlüsselwort angegeben werden müssen. Pfeilfunktionen müssen keinen Wert zurückgeben. Wenn die Ausführung des Blockkörpers das Ende erreicht, ohne auf eine return-Anweisung zu stoßen, gibt die Funktion wie andere Funktionen undefined zurück.

js
// Expression body
const add = (a, b) => a + b; // Implicitly returns a + b

// Block body
const add2 = (a, b) => {
  console.log(a, b);
  return a + b; // Must explicitly return a value
};

// No return value
const add3 = (b) => {
  a += b;
  // No return statement, so returns undefined
};

Die Rückgabe von Objektliteralen mit der Ausdruckskörpersyntax (params) => { object: literal } funktioniert nicht wie erwartet.

js
const func = () => { foo: 1 };
// Calling func() returns undefined!

const func2 = () => { foo: function () {} };
// SyntaxError: function statement requires a name

const func3 = () => { foo() {} };
// SyntaxError: Unexpected token '{'

Dies liegt daran, dass JavaScript die Pfeilfunktion nur dann als Ausdruckskörper ansieht, wenn das Token nach dem Pfeil keine linke geschweifte Klammer ist, sodass der Code innerhalb der Klammern ({}) als Folge von Anweisungen geparst wird, wobei foo ein Label ist, kein Schlüssel in einem Objektliteral.

Um dies zu beheben, wickle das Objektliteral in Klammern:

js
const func = () => ({ foo: 1 });

Kann nicht als Methoden verwendet werden

Pfeilfunktion-Ausdrücke sollten nur für Nicht-Methoden-Funktionen verwendet werden, da sie kein eigenes this haben. Sehen wir uns an, was passiert, wenn wir versuchen, sie als Methoden zu verwenden:

js
"use strict";

const obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c() {
    console.log(this.i, this);
  },
};

obj.b(); // logs undefined, Window { /* … */ } (or the global object)
obj.c(); // logs 10, Object { /* … */ }

Ein weiteres Beispiel mit Object.defineProperty():

js
"use strict";

const obj = {
  a: 10,
};

Object.defineProperty(obj, "b", {
  get: () => {
    console.log(this.a, typeof this.a, this); // undefined 'undefined' Window { /* … */ } (or the global object)
    return this.a + 10; // represents global object 'Window', therefore 'this.a' returns 'undefined'
  },
});

Da ein Funktionskörper einer Klasse ein this-Kontext hat, schließen Pfeilfunktionen über das this der Klasse und das this im Körper der Pfeilfunktion zeigt korrekt auf die Instanz (oder die Klasse selbst, für statische Felder). Da es sich jedoch um einen Abschluss handelt und nicht um das eigene Binding der Funktion, ändert sich der Wert von this nicht basierend auf dem Ausführungskontext.

js
class C {
  a = 1;
  autoBoundMethod = () => {
    console.log(this.a);
  };
}

const c = new C();
c.autoBoundMethod(); // 1
const { autoBoundMethod } = c;
autoBoundMethod(); // 1
// If it were a normal method, it should be undefined in this case

Eigenschaften von Pfeilfunktionen werden oft als "automatisch gebundene Methoden" bezeichnet, weil das Äquivalent mit normalen Methoden ist:

js
class C {
  a = 1;
  constructor() {
    this.method = this.method.bind(this);
  }
  method() {
    console.log(this.a);
  }
}

Hinweis: Klassenfelder werden auf der Instanz definiert, nicht auf dem Prototyp, sodass bei jeder Instanzerstellung eine neue Funktionsreferenz erstellt und ein neuer Abschluss zugewiesen wird, was potenziell mehr Speicherplatz beansprucht als eine normale ungebundene Methode.

Aus ähnlichen Gründen sind die Methoden call(), apply() und bind() für Pfeilfunktionen nicht nützlich, da Pfeilfunktionen this basierend auf dem Kontext festlegen, in dem sie definiert sind, und der this-Wert sich nicht ändert, basierend darauf, wie die Funktion aufgerufen wird.

Kein Binding von Arguments

Pfeilfunktionen haben kein eigenes arguments-Objekt. In diesem Beispiel bezieht sich arguments daher auf die Argumente des umschließenden Scopes:

js
function foo(n) {
  const f = () => arguments[0] + n; // foo's implicit arguments binding. arguments[0] is n
  return f();
}

foo(3); // 3 + 3 = 6

In den meisten Fällen ist die Verwendung von Rest-Parametern eine gute Alternative zur Verwendung eines arguments-Objekts.

js
function foo(n) {
  const f = (...args) => args[0] + n;
  return f(10);
}

foo(1); // 11

Können nicht als Konstruktoren verwendet werden

Pfeilfunktionen können nicht als Konstruktoren verwendet werden und lösen einen Fehler aus, wenn sie mit new aufgerufen werden. Sie haben auch keine prototype-Eigenschaft.

js
const Foo = () => {};
const foo = new Foo(); // TypeError: Foo is not a constructor
console.log("prototype" in Foo); // false

Können nicht als Generatoren verwendet werden

Das Schlüsselwort yield kann nicht im Körper einer Pfeilfunktion verwendet werden (außer wenn es innerhalb von Generatorfunktionen genutzt wird, die weiter innerhalb der Pfeilfunktion verschachtelt sind). Daher können Pfeilfunktionen nicht als Generatoren verwendet werden.

Zeilenumbruch vor dem Pfeil

Eine Pfeilfunktion darf keinen Zeilenumbruch zwischen ihren Parametern und ihrem Pfeil enthalten.

js
const func = (a, b, c)
  => 1;
// SyntaxError: Unexpected token '=>'

Zum Zweck der Formatierung können Sie den Zeilenumbruch nach dem Pfeil einfügen oder Klammern/geschweifte Klammern um den Funktionskörper verwenden, wie unten gezeigt. Sie können auch Zeilenumbrüche zwischen den Parametern einfügen.

js
const func = (a, b, c) =>
  1;

const func2 = (a, b, c) => (
  1
);

const func3 = (a, b, c) => {
  return 1;
};

const func4 = (
  a,
  b,
  c,
) => 1;

Vorrang des Pfeils

Obwohl der Pfeil in einer Pfeilfunktion kein Operator ist, haben Pfeilfunktionen spezielle Parsing-Regeln, die im Vergleich zu normalen Funktionen anders mit der Operatorvorrang interagieren.

js
let callback;

callback = callback || () => {};
// SyntaxError: invalid arrow-function arguments

Da => eine niedrigere Vorrangstellung hat als die meisten Operatoren, sind Klammern erforderlich, um zu verhindern, dass callback || () als Argumentenliste der Pfeilfunktion geparst wird.

js
callback = callback || (() => {});

Beispiele

Verwendung von Pfeilfunktionen

js
// An empty arrow function returns undefined
const empty = () => {};

(() => "foobar")();
// Returns "foobar"
// (this is an Immediately Invoked Function Expression)

const simple = (a) => (a > 15 ? 15 : a);
simple(16); // 15
simple(10); // 10

const max = (a, b) => (a > b ? a : b);

// Easy array filtering, mapping, etc.
const arr = [5, 6, 13, 0, 1, 18, 23];

const sum = arr.reduce((a, b) => a + b);
// 66

const even = arr.filter((v) => v % 2 === 0);
// [6, 0, 18]

const double = arr.map((v) => v * 2);
// [10, 12, 26, 0, 2, 36, 46]

// More concise promise chains
promise
  .then((a) => {
    // …
  })
  .then((b) => {
    // …
  });

// Arrow functions without parameters
setTimeout(() => {
  console.log("I happen sooner");
  setTimeout(() => {
    // deeper code
    console.log("I happen later");
  }, 1);
}, 1);

Verwendung von call, bind und apply

Die Methoden call(), apply() und bind() funktionieren wie erwartet mit traditionellen Funktionen, da wir den Scope für jede dieser Methoden festlegen:

js
const obj = {
  num: 100,
};

// Setting "num" on globalThis to show how it is NOT used.
globalThis.num = 42;

// A traditional function to operate on "this"
function add(a, b, c) {
  return this.num + a + b + c;
}

console.log(add.call(obj, 1, 2, 3)); // 106
console.log(add.apply(obj, [1, 2, 3])); // 106
const boundAdd = add.bind(obj);
console.log(boundAdd(1, 2, 3)); // 106

Mit Pfeilfunktionen, da unsere add-Funktion im Wesentlichen im globalThis (globalen) Scope erstellt wird, nimmt sie an, dass this das globalThis ist.

js
const obj = {
  num: 100,
};

// Setting "num" on globalThis to show how it gets picked up.
globalThis.num = 42;

// Arrow function
const add = (a, b, c) => this.num + a + b + c;

console.log(add.call(obj, 1, 2, 3)); // 48
console.log(add.apply(obj, [1, 2, 3])); // 48
const boundAdd = add.bind(obj);
console.log(boundAdd(1, 2, 3)); // 48

Der vielleicht größte Vorteil von Pfeilfunktionen liegt in Methoden wie setTimeout() und EventTarget.prototype.addEventListener(), die normalerweise eine Art von Abschluss, call(), apply() oder bind() erfordern, um sicherzustellen, dass die Funktion im richtigen Kontext ausgeführt wird.

Mit traditionellen Funktionsausdrücken funktioniert Code wie dieser nicht wie erwartet:

js
const obj = {
  count: 10,
  doSomethingLater() {
    setTimeout(function () {
      // the function executes on the window scope
      this.count++;
      console.log(this.count);
    }, 300);
  },
};

obj.doSomethingLater(); // logs "NaN", because the property "count" is not in the window scope.

Mit Pfeilfunktionen bleibt der this-Kontext einfacher erhalten:

js
const obj = {
  count: 10,
  doSomethingLater() {
    // The method syntax binds "this" to the "obj" context.
    setTimeout(() => {
      // Since the arrow function doesn't have its own binding and
      // setTimeout (as a function call) doesn't create a binding
      // itself, the "obj" context of the outer method is used.
      this.count++;
      console.log(this.count);
    }, 300);
  },
};

obj.doSomethingLater(); // logs 11

Spezifikationen

Specification
ECMAScript® 2026 Language Specification
# sec-arrow-function-definitions

Browser-Kompatibilität

Siehe auch