Читать книгу JavaScript – Das Handbuch für die Praxis - David Flanagan - Страница 112
4.13.2?? – der Erstdefiniert-Operator
ОглавлениеDer Operator ?? wird zu seinem ersten definierten Operanden ausgewertet: Wenn sein linker Operand nicht null und nicht undefined ist, wird dieser Wert zurückgeliefert. Andernfalls gibt er den Wert des rechten Operanden zurück. Wie die Operatoren && und || ist auch ?? ein »kurzschließender« Operator: Er wertet seinen zweiten Operanden nur dann aus, wenn der erste Operand null oder undefined ergibt. Wenn der Ausdruck a keine Seiteneffekte hat, ist der Ausdruck a ?? b äquivalent zu:
(a !== null && a !== undefined) ? a : b
?? ist eine nützliche Alternative zu || (siehe 4.10.2), wenn Sie den ersten definierten Operanden und nicht den ersten »irgendwie wahren« Operanden auswählen möchten. Obwohl || nominell ein logischer ODER-Operator ist, wird er in JavaScript auch gern verwendet, um den ersten »irgendwie falschen« Operanden auszuwählen, beispielsweise so:
// Wenn maxWidth truthy ist, nimm diesen Wert, andernfalls einen Wert
// im Objekt preferences. Ist das nicht truthy, nimm die angegebene Konstante.
let max = maxWidth || preferences.maxWidth || 500;
Das Problem bei dieser Verwendung ist, dass null (0), die leere Zeichenkette und false allesamt nicht-strikt falsche Werte sind, die unter bestimmten Umständen durchaus valide sein können. Wenn in diesem Codebeispiel maxWidth gleich null (0) ist, wird dieser Wert ignoriert. Aber wenn wir den ||-Operator durch ?? ersetzen, erhalten wir einen Ausdruck, in dem 0 ein gültiger Wert ist:
// Wenn maxWidth definiert ist, nimm diesen Wert, andernfalls einen Wert
// im Objekt preferences. Wenn es auch den nicht gibt, greife auf die Konstante
// zurück.
let max = maxWidth ?? preferences.maxWidth ?? 500;
Hier sind weitere Beispiele, die zeigen, wie ?? funktioniert, wenn der erste Operand nicht-strikt falsch ist. Ist er zwar falsy, aber definiert, gibt ?? diesen ersten Operanden zurück. Nur wenn er »nullish« ist (also »nullartig«: null oder undefiniert), wertet dieser Operator den zweiten Operanden aus und gibt diesen zurück:
let options = { timeout: 0, title: "", verbose: false, n: null };
options.timeout ?? 1000 // => 0: wie im Objekt definiert.
options.title ?? "Untitled" // => "": wie im Objekt definiert.
options.verbose ?? true // => false: wie im Objekt definiert.
options.quiet ?? false // => false: Eigenschaft ist nicht definiert.
options.n ?? 10 // => 10: Eigenschaft ist null.
Beachten Sie bitte, dass die Ausdrücke timeout, title und verbose hier unterschiedliche Werte hätten, wenn wir || anstelle von ?? verwendeten.
Der ??-Operator ähnelt den Operatoren && und ||, hat aber weder höheren noch niedrigeren Vorrang als diese. Wenn Sie ihn in einem Ausdruck zusammen mit einem dieser Operatoren einsetzen, müssen Sie explizite Klammern verwenden, um die Ausführungsreihenfolge festzulegen:
(a ?? b) || c // ?? zuerst, dann ||
a ?? (b || c) // || zuerst, dann ??
a ?? b || c // SyntaxError: Hier sind Klammern erforderlich.
Der ??-Operator wurde mit ES2020 eingeführt und wird Ende 2020 von allen gängigen Desktopbrowsern unterstützt (bei Browsern für Mobilgeräte bestehen noch kleine Lücken). Dieser Operator wird formal als »Nullish-Coalescing«-Operator bezeichnet (wörtlich im Deutschen etwa »nullartiger Zusammenführungsoperator«). Ich vermeide den Begriff aber, weil dieser Operator zwar einen seiner Operanden auswählt, sie aber in keiner für mich erkennbaren Weise »zusammenführt«. Deshalb bezeichne ich ihn lieber als Erstdefiniert-Operator (First-defined Operator), weil er den ersten definierten Operanden auswählt.