Signatur
Beschreibung
caller ist ein Überbleibsel aus der Frühzeit von JavaScript. Wird die Eigenschaft auf einer Funktion f gelesen, während f gerade ausgeführt wird, liefert sie die Funktion, die f aufgerufen hat. Kam der Aufruf aus Code auf oberster Ebene (Skript oder Modul), ist der Wert null. Früher nutzte man sie für einfaches Debugging oder um „Aufrufketten“ selbst nachzubauen.
Die Eigenschaft gehört nicht zum ECMAScript-Standard. Die Spezifikation legt nur fest, dass Function.prototype einen sogenannten Poison-Pill-Accessor für caller besitzt: Lesen oder Schreiben löst bedingungslos einen TypeError aus. Engines wie V8 und SpiderMonkey geben nicht-strikten, „klassischen“ Funktionen jedoch eine eigene caller-Eigenschaft, die den aufrufenden Kontext zurückgibt. Das gilt nur für Funktionen, die mit function deklariert oder als Ausdruck definiert wurden, und nur außerhalb des Strict Mode.
Für Strict-Mode-Funktionen, Pfeilfunktionen, Methoden-Kurzschreibweisen, Klassen, async-Funktionen und Generatoren gibt es keine eigene Eigenschaft. Dort greift der geerbte Poison-Pill-Accessor, und der Zugriff wirft einen TypeError. Wurde eine nicht-strikte Funktion von einer Strict-Mode-Funktion aufgerufen, liefert caller ebenfalls null, damit keine strikte Funktion nach außen sichtbar wird.
In modernem Code sollte man caller nicht verwenden. Für Debugging eignen sich new Error().stack, console.trace() oder die Entwicklerwerkzeuge des Browsers. Wenn eine Funktion wissen muss, wer sie aufgerufen hat, übergibt man diese Information besser ausdrücklich als Parameter.
Rückgabewert
null, wenn sie von oberster Ebene, von einer Strict-Mode-Funktion oder gerade gar nicht aufgerufen wird. Bei Strict-Mode-Funktionen, Pfeilfunktionen, Klassen, async-Funktionen und Generatoren wirft der Zugriff stattdessen einen TypeError.Beispiele
Aufrufer in nicht-striktem Code ermitteln
// Klassisches Skript ohne "use strict"
function ziel() {
if (ziel.caller === null) {
console.log('Aufruf von oberster Ebene');
} else {
console.log(`Aufgerufen von: ${ziel.caller.name}`);
}
}
function rufer() {
ziel();
}
rufer();
ziel();
TypeError bei Strict Mode und Pfeilfunktionen
const pfeil = () => {};
function strikt() {
'use strict';
}
for (const fn of [pfeil, strikt]) {
try {
console.log(fn.caller);
} catch (err) {
console.log(`${fn.name}: ${err.constructor.name}`);
}
}
Moderne Alternative: Aufrufstapel über Error.stack
const log = (nachricht) => {
// Zeile 0: "Error", Zeile 1: log selbst, Zeile 2: der Aufrufer
const zeilen = new Error().stack?.split('\n') ?? [];
const aufrufer = zeilen[2]?.trim() ?? 'unbekannt';
console.log(`[${aufrufer}] ${nachricht}`);
};
const speichern = () => log('Daten gespeichert');
speichern();
Besser: Kontext ausdrücklich übergeben
const protokolliere = (quelle, nachricht) => {
console.log(`[${quelle}] ${nachricht}`);
};
const ladeBenutzer = async (id) => {
protokolliere('ladeBenutzer', `Lade Benutzer ${id}`);
return { id, name: 'Ada' };
};
ladeBenutzer(42).then((u) => console.log(u.name));
// Wichtig · Fallstricke
- Nicht standardisiert und veraltet: Nicht in Produktionscode verwenden. Das Verhalten unterscheidet sich zwischen den Engines, etwa bei Rekursion, eingebauten Funktionen oder bei Aufrufen über
eval. - Strict Mode: ES-Module und Klassenrümpfe laufen automatisch im Strict Mode. Dort wirft jeder Zugriff auf
callereinenTypeError. Das Gleiche gilt für Pfeilfunktionen, Methoden-Kurzschreibweisen, async-Funktionen und Generatoren. - Kein echter Aufrufstapel:
callerliefert nur eine Funktionsreferenz, keine Stapelrahmen. Bei rekursiven Aufrufen lässt sich mitf.caller.callerkeine vollständige Kette rekonstruieren, weil dieselbe Funktion mehrfach vorkommt und die Schleife nicht aufzulösen ist. - Performance und Sicherheit: Die Eigenschaft hindert Engines an Optimierungen wie Inlining. Außerdem kann sie Referenzen auf fremde Funktionen offenlegen. Genau deshalb wurde sie im Strict Mode gesperrt.
- Die verwandte Eigenschaft
arguments.callee.callerist ebenfalls veraltet und im Strict Mode verboten. - Als Alternativen eignen sich
new Error().stack(Format nicht standardisiert),console.trace()und Haltepunkte in den Entwicklerwerkzeugen.