Читать книгу JavaScript – Das Handbuch für die Praxis - David Flanagan - Страница 78
4.5.1Bedingter Aufruf
ОглавлениеAb ES2020 können Sie eine Funktion auch mit ?.() anstelle von () aufrufen. Normalerweise wird beim Aufruf einer Funktion ein TypeError ausgelöst, wenn der Ausdruck links von der Klammer null oder undefined lautet oder keine Funktion ist. Bei der neuen Aufrufsyntax der Form ?.() wird der gesamte Aufrufausdruck zu undefined ausgewertet, wenn der Ausdruck links vom ?. zu null oder undefined ausgewertet wird, und zudem wird keine Ausnahme ausgelöst.
Array-Objekte verfügen über eine sort()-Methode, der optional ein Funktionsargument übergeben werden kann, das die gewünschte Sortierreihenfolge für die Array-Elemente festlegt. Wollte man vor ES2020 eine Methode wie sort() schreiben, die ein optionales Funktionsargument benötigt, hätte man normalerweise mit einer if-Anweisung überprüft, ob das Funktionsargument definiert wurde. Erst danach hätte man es dann im Funktionskörper aufgerufen:
function square(x, log) { // Das zweite Argument ist eine optionale Funktion.
if (log) { // Falls die optionale Funktion übergeben wird,
log(x); // wird sie aufgerufen.
}
return x * x; // Das Quadrat des Arguments wird zurückgegeben.
}
Mit der bedingten Aufrufsyntax von ES2020 können Sie den Funktionsaufruf jedoch einfach mit ?.() formulieren. Damit stellen Sie sicher, dass der Aufruf nur dann erfolgt, wenn es auch tatsächlich einen aufzurufenden Wert gibt:
function square(x, log) { // Das zweite Argument ist eine optionale Funktion.
log?.(x); // Rufen Sie die Funktion auf, falls es eine gibt.
return x * x; // Das Quadrat des Arguments wird zurückgegeben.
}
Denken Sie aber daran, dass ?.() nur prüft, ob die linke Seite null oder undefined ist, aber nicht, ob der Wert tatsächlich eine Funktion ist. Die square()-Funktion des obigen Beispiels würde also immer noch eine Ausnahme auslösen, wenn Sie ihr z.B. zwei Zahlen übergeben (anstelle einer Zahl und einer Funktion).
Wie die Ausdrücke für den bedingten Eigenschaftszugriff (siehe 4.4.1) ist der Funktionsaufruf mit ?.() »kurzschließend« (short-circuiting): Die Auswertung wird vorzeitig unterbrochen, wenn der Wert links von ?. null oder undefined lautet. Keiner der Argumentausdrücke innerhalb der Klammern wird dann noch ausgewertet:
let f = null, x = 0;
try {
f(x++); // Löst einen TypeError aus, weil f null ist.
} catch(e) {
x // => 1: x wurde inkrementiert, bevor die Ausnahme ausgelöst wurde.
}
f?.(x++) // => undefined: f ist null, aber es wird keine Ausnahme ausgelöst.
x // => 1: Inkrementierung wurde (wegen "Kurzschließung") übersprungen.
Bedingte Aufrufausdrücke mit ?.() funktionieren für Methoden genauso wie für Funktionen. Da der Methodenaufruf jedoch auch den Zugriff auf Eigenschaften beinhaltet, sollten Sie sich einen Moment Zeit nehmen, um sicherzustellen, dass Sie die Unterschiede zwischen den folgenden Ausdrücken verstehen:
o.m() // Normaler (regulärer, nicht bedingter) Zugriff auf Eigenschaften,
// normaler Aufruf.
o?.m() // Bedingter Zugriff auf Eigenschaften, normaler Aufruf.
o.m?.() // Normaler Zugriff auf Eigenschaften, bedingter Aufruf.
Im ersten Ausdruck muss o ein Objekt mit einer Eigenschaft m und der Wert dieser Eigenschaft muss eine Funktion sein. Wenn im zweiten Ausdruck o null oder undefined ist, wird der Ausdruck zu undefined ausgewertet. Hat o aber einen anderen Wert, muss es eine Eigenschaft m besitzen, deren Wert eine Funktion ist. Und im dritten Ausdruck darf o nicht null oder undefined sein. Falls es keine Eigenschaft m besitzt oder wenn der Wert dieser Eigenschaft null ist, wird der gesamte Ausdruck zu undefined ausgewertet.
Der bedingte Aufruf mit ?.() ist – wie der bedingte Eigenschaftszugriff – eine der neuesten Funktionen von JavaScript. Stand Anfang 2020 wird auch diese neue Syntax in den aktuellen oder Betaversionen der meisten gängigen Browser unterstützt.