Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.
Pfeilfunktionen (Arrow Functions)
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.
EinPfeilfunktionsausdruck ist eine kompakte Alternative zu einem traditionellenFunktionsausdruck, mit einigen semantischen Unterschieden und bewussten Einschränkungen bei der Verwendung:
- Pfeilfunktionen haben keine eigenenBindungen zu
this,argumentsodersuperund sollten nicht alsMethoden verwendet werden. - Pfeilfunktionen können nicht alsKonstruktoren verwendet werden. Das Aufrufen mit
newlöst einenTypeErroraus. Sie haben auch keinen Zugriff auf das Schlüsselwortnew.target. - Pfeilfunktionen können innerhalb ihres Körpers kein
yieldverwenden und können nicht als Generatorfunktionen erstellt werden.
In diesem Artikel
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
() => expressionparam => expression(param) => expression(param1, paramN) => expression() => { statements}param => { statements}(param1, paramN) => { statements}Restparameter,Standardparameter undDestrukturierung innerhalb der Parameter werden unterstützt und erfordern immer Klammern:
(a, b, ...r) => expression(a = 400, b = 20, c) => expression([a, b] = [10, 20]) => expression({ a, b } = { a: 10, b: 20 }) => expressionPfeilfunktionen könnenasync sein, indem der Ausdruck mit dem Schlüsselwortasync versehen wird.
async param => expressionasync (param1, param2, ...paramN) => { statements}Beschreibung
Lassen Sie uns eine traditionelle anonyme Funktion Schritt für Schritt auf die einfachste Pfeilfunktion herunterbrechen. Jeder Schritt auf dem Weg ist eine gültige Pfeilfunktion.
Hinweis:Traditionelle Funktionsausdrücke und Pfeilfunktionen haben mehr Unterschiede als nur ihre Syntax. Wir werden ihre Verhaltensunterschiede in den nächsten Abschnitten genauer vorstellen.
// 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 parenthesesa => a + 100;Im obigen Beispiel können sowohl die Klammern um den Parameter als auch die geschweiften Klammern um den Funktionskörper weggelassen werden. Sie können jedoch nur unter bestimmten Umständen weggelassen werden.
Die Klammern können nur weggelassen werden, wenn die Funktion einen einzelnen einfachen Parameter hat. Hat sie mehrere Parameter, keine Parameter oder Standard-, destrukturierte oder Restparameter, sind die Klammern um die Parameterliste erforderlich.
// 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. Hat der Körper Anweisungen, sind die geschweiften Klammern erforderlich. In diesem Fall müssen Rückgabewerte explizit mit dem Schlüsselwortreturn angegeben werden. Pfeilfunktionen können nicht erraten, was oder wann Sie etwas zurückgeben möchten.
// 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, die es Ihnen ermöglicht, sie über diese Variable aufzurufen.
// Traditional Functionfunction bob(a) { return a + 100;}// Arrow Functionconst bob2 = (a) => a + 100;Funktionskörper
Pfeilfunktionen können entweder einenAusdruckskörper oder den üblichenBlockkörper haben.
In einem Ausdruckskörper wird nur ein einziger Ausdruck angegeben, der zum impliziten Rückgabewert wird. Der Blockkörper ist analog zu traditionellen Funktionskörpern, bei denen Rückgabewerte explizit mit dem Schlüsselwortreturn angegeben werden müssen. Pfeilfunktionen müssen keinen Wert zurückgeben. Wenn die Ausführung des Blockkörpers ohne einereturn-Anweisung endet, gibt die Funktionundefined zurück wie andere Funktionen.
// Expression bodyconst add = (a, b) => a + b; // Implicitly returns a// Block bodyconst add2 = (a, b) => { console.log(a, b); return a + b; // Must explicitly return a value};// No return valueconst add3 = (b) => { a += b; // No return statement, so returns undefined};Das Zurückgeben von Objektliteralen unter Verwendung der Ausdruckskörpersyntax(params) => { object: literal } funktioniert nicht wie erwartet.
const func = () => { foo: 1 };// Calling func() returns undefined!const func2 = () => { foo: function () {} };// SyntaxError: function statement requires a nameconst func3 = () => { foo() {} };// SyntaxError: Unexpected token '{'Dies liegt daran, dass JavaScript die Pfeilfunktion nur als eine Funktion mit Ausdruckskörper betrachtet, wenn das Token nach dem Pfeil keine geschweifte Klammer ist. Der Code innerhalb geschweifter Klammern ({}) wird als Folge von Anweisungen geparst, bei denenfoo einLabel ist, kein Schlüssel in einem Objektliteral.
Um dies zu beheben, setzen Sie das Objektliteral in Klammern:
const func = () => ({ foo: 1 });Können nicht als Methoden verwendet werden
Pfeilfunktionsausdrücke sollten nur für Nicht-Methoden-Funktionen verwendet werden, da sie kein eigenesthis haben. Schauen wir uns an, was passiert, wenn wir versuchen, sie als Methoden zu verwenden:
"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 mitObject.defineProperty():
"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 der Körper einerKlasse einenthis-Kontext hat, schließen Pfeilfunktionen alsKlassenfelder über denthis-Kontext der Klasse, und dasthis im Körper der Pfeilfunktion zeigt korrekt auf die Instanz (oder die Klasse selbst, fürstatische Felder). Da es sich jedoch um eineSchließung handelt und nicht um die eigene Bindung der Funktion, ändert sich der Wert vonthis nicht basierend auf dem Ausführungskontext.
class C { a = 1; autoBoundMethod = () => { console.log(this.a); };}const c = new C();c.autoBoundMethod(); // 1const { autoBoundMethod } = c;autoBoundMethod(); // 1// If it were a normal method, it should be undefined in this casePfeilfunktions-Eigenschaften werden oft als "automatisch gebundene Methoden" bezeichnet, weil das Äquivalent bei normalen Methoden ist:
class C { a = 1; constructor() { this.method = this.method.bind(this); } method() { console.log(this.a); }}Hinweis:Klassenfelder werden auf derInstanz definiert, nicht auf demPrototypen, sodass jede Instanzerstellung einen neuen Funktionsverweis erstellt und eine neue Schließung zuweist, was potenziell zu mehr Speichernutzung als bei einer normalen ungebundenen Methode führen kann.
Aus ähnlichen Gründen sind die Methodencall(),apply() undbind() nicht nützlich, wenn sie auf Pfeilfunktionen angewendet werden, da Pfeilfunktionenthis basierend auf dem Scope festlegen, in dem die Pfeilfunktion definiert ist, und derthis-Wert sich nicht ändert, basierend darauf, wie die Funktion aufgerufen wird.
Keine Bindung von Arguments
Pfeilfunktionen haben kein eigenesarguments-Objekt. In diesem Beispiel istarguments also ein Verweis auf die Argumente des umgebenden Scopes:
function foo(n) { const f = () => arguments[0] + n; // foo's implicit arguments binding. arguments[0] is n return f();}foo(3); // 3 + 3 = 6In den meisten Fällen ist die Verwendung vonRestparameterneine gute Alternative zur Verwendung einesarguments-Objekts.
function foo(n) { const f = (...args) => args[0] + n; return f(10);}foo(1); // 11Können nicht als Konstruktoren verwendet werden
Pfeilfunktionen können nicht als Konstruktoren verwendet werden und werfen einen Fehler, wenn sie mitnew aufgerufen werden. Sie haben auch keineprototype-Eigenschaft.
const Foo = () => {};const foo = new Foo(); // TypeError: Foo is not a constructorconsole.log("prototype" in Foo); // falseKönnen nicht als Generatoren verwendet werden
Das Schlüsselwortyield kann nicht im Körper einer Pfeilfunktion verwendet werden (außer wenn es in weiter verschachtelten Generatorfunktionen innerhalb der Pfeilfunktion verwendet wird). Daher können Pfeilfunktionen nicht als Generatoren verwendet werden.
Zeilenumbruch vor dem Pfeil
Eine Pfeilfunktion kann keinen Zeilenumbruch zwischen ihren Parametern und ihrem Pfeil enthalten.
const func = (a, b, c) => 1;// SyntaxError: Unexpected token '=>'Zum Zwecke der Formatierung können Sie den Zeilenumbruch nach dem Pfeil setzen oder Klammern/geschweifte Klammern um den Funktionskörper verwenden, wie unten gezeigt. Sie können auch Zeilenumbrüche zwischen den Parametern setzen.
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 Parserregeln, die anders mit derOperatorpräzedenz interagieren als reguläre Funktionen.
let callback;callback = callback || () => {};// SyntaxError: invalid arrow-function argumentsDa=> eine niedrigere Präzedenz als die meisten Operatoren hat, sind Klammern notwendig, um zu vermeiden, dasscallback || () als Argumentliste der Pfeilfunktion geparst wird.
callback = callback || (() => {});Beispiele
>Verwenden von Pfeilfunktionen
// An empty arrow function returns undefinedconst empty = () => {};(() => "foobar")();// Returns "foobar"// (this is an Immediately Invoked Function Expression)const simple = (a) => (a > 15 ? 15 : a);simple(16); // 15simple(10); // 10const 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);// 66const 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 chainspromise .then((a) => { // … }) .then((b) => { // … });// Arrow functions without parameterssetTimeout(() => { console.log("I happen sooner"); setTimeout(() => { // deeper code console.log("I happen later"); }, 1);}, 1);Verwenden von call, bind und apply
Die Methodencall(),apply(), undbind() funktionieren wie erwartet mit traditionellen Funktionen, da wir den Scope für jede der Methoden festlegen:
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)); // 106console.log(add.apply(obj, [1, 2, 3])); // 106const boundAdd = add.bind(obj);console.log(boundAdd(1, 2, 3)); // 106Bei Pfeilfunktionen geht unsereadd-Funktion im Grunde vomglobalThis (globalen) Scope aus und nimmt an, dassthis dasglobalThis ist.
const obj = { num: 100,};// Setting "num" on globalThis to show how it gets picked up.globalThis.num = 42;// Arrow functionconst add = (a, b, c) => this.num + a + b + c;console.log(add.call(obj, 1, 2, 3)); // 48console.log(add.apply(obj, [1, 2, 3])); // 48const boundAdd = add.bind(obj);console.log(boundAdd(1, 2, 3)); // 48Vielleicht der größte Vorteil der Verwendung von Pfeilfunktionen liegt bei Methoden wiesetTimeout() undEventTarget.prototype.addEventListener(), die üblicherweise eine Art von Schließung,call(),apply() oderbind() erfordern, um sicherzustellen, dass die Funktion im richtigen Scope ausgeführt wird.
Mit traditionellen Funktionsausdrücken funktioniert der folgende Code nicht wie erwartet:
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 derthis-Scope leichter erhalten:
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 11Spezifikationen
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-arrow-function-definitions> |
Browser-Kompatibilität
Siehe auch
- Leitfaden zu Funktionen
- Funktionen
functionfunctionexpression- ES6 In Depth: Arrow functions auf hacks.mozilla.org (2015)