Signatur
Beschreibung
Ein Funktionsausdruck (engl. function expression, kurz FE) erlaubt es, eine Funktion direkt innerhalb eines größeren Ausdrucks zu definieren – etwa als Wert einer Variable, als Argument eines Funktionsaufrufs oder als Rückgabewert einer anderen Funktion. Im Gegensatz zu einer Funktionsdeklaration (function foo() {}) wird ein Funktionsausdruck nicht gehoben (kein Hoisting): Die Funktion ist erst ab der Zeile verfügbar, in der sie zugewiesen wird.
Funktionsausdrücke können anonym sein (kein Name nach dem function-Schlüsselwort) oder einen optionalen Namen tragen. Ein benannter Funktionsausdruck hat den Vorteil, dass der Name im Fehler-Stack-Trace erscheint und innerhalb des Funktionskörpers für Rekursion verwendet werden kann. Der Name ist jedoch ausschließlich innerhalb des eigenen Funktionskörpers sichtbar – im umgebenden Scope ist er nicht zugänglich.
Typische Einsatzgebiete sind Callbacks (z. B. bei Array.prototype.map oder setTimeout), sofort ausgeführte Funktionsausdrücke (IIFE), das Zuweisen von Methoden an Objekte sowie das Erzeugen von Closures. Für viele dieser Anwendungsfälle bieten sich heute auch Pfeilfunktionen (() => {}) an, die jedoch kein eigenes this, kein arguments-Objekt und keine eigene new.target-Bindung besitzen.
- Kein Hoisting: Anders als Funktionsdeklarationen können FEs erst nach ihrer Zuweisung aufgerufen werden.
- Optionaler Name: Nur innerhalb des Funktionskörpers und im Debugger sichtbar.
- Closure: FEs schließen über den umgebenden lexikalischen Scope ab – Variablen der äußeren Funktion bleiben erhalten.
- IIFE: Werden FEs direkt mit
(function() { ... })()aufgerufen, erzeugen sie einen isolierten Scope.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $name | string | Optionaler Name der Funktion. Nur innerhalb des Funktionskörpers selbst sichtbar (z. B. für Rekursion). Verbessert die Lesbarkeit von Stack-Traces. | |
| $param1, …, paramN | string | Kommagetrennte Liste formaler Parameternamen. Unterstützt Rest-Parameter (...rest), Standardwerte (param = default) und Destructuring-Muster. |
|
| $statements | statement | Der Funktionskörper – beliebige JavaScript-Anweisungen, die beim Aufruf der Funktion ausgeführt werden. |
Rückgabewert
Function-Objekt, das den definierten Funktionskörper repräsentiert und aufgerufen, übergeben oder gespeichert werden kann.Beispiele
Anonymer Funktionsausdruck als Callback
const numbers = [3, 1, 4, 1, 5, 9];
const sorted = numbers.sort(function (a, b) {
return a - b;
});
console.log(sorted);
Benannter Funktionsausdruck mit Rekursion
const factorial = function fac(n) {
// 'fac' ist nur hier im Körper sichtbar
if (n <= 1) return 1;
return n * fac(n - 1);
};
console.log(factorial(6));
// 'fac' außerhalb nicht zugreifbar:
try {
fac(3);
} catch (e) {
console.error(e.message);
}
Sofort ausgeführter Funktionsausdruck (IIFE)
const result = (function (base) {
const factor = 2; // isolierter Scope
return base * factor;
})(21);
console.log(result);
console.log(typeof factor); // nicht im äußeren Scope
Funktionsausdruck als Methode und Closure
const makeCounter = function (start = 0) {
let count = start;
return {
increment: function () { count += 1; },
decrement: function () { count -= 1; },
value: function () { return count; },
};
};
const counter = makeCounter(10);
counter.increment();
counter.increment();
counter.decrement();
console.log(counter.value());
// Wichtig · Fallstricke
Kein Hoisting: Eine Variable, die mit const oder let einen Funktionsausdruck hält, befindet sich bis zur Initialisierungszeile in der Temporal Dead Zone. Der Versuch, sie vorher aufzurufen, wirft einen ReferenceError.
Kein eigenes this bei Pfeilfunktionen: Als moderner Ersatz bieten sich Pfeilfunktionen (const fn = () => {}) an, die allerdings kein eigenes this, kein arguments-Objekt und keinen new-Aufruf unterstützen. Benötigt die Funktion eines davon, muss ein klassischer Funktionsausdruck verwendet werden.
Strict Mode: In Modulen und Klassen wird der Inhalt eines Funktionsausdrucks automatisch im Strict Mode ausgeführt. Ein explizites "use strict"; am Anfang des Funktionskörpers ist trotzdem möglich und empfohlen, wenn kein Modul-Kontext vorliegt.
Benannte FE im Debugger: Es ist Best Practice, Funktionsausdrücken stets einen Namen zu geben, damit Stack-Traces und Profiler-Ausgaben lesbar bleiben – auch wenn der Name außen nicht benötigt wird.