Zwei Arten von Type Coercion
JavaScript nimmt es mit Typen nicht so genau. Bekommt ein Operator einen Wert vom "falschen" Typ, wirft die Sprache keinen Fehler — sie wandelt einfach um. Genau diese Umwandlung nennt man Type Coercion (auf Deutsch oft schlicht Typumwandlung), und davon gibt es zwei Varianten:
- Explizite Typumwandlung — du forderst sie an:
Number("42"),String(99),Boolean(value). - Implizite Typumwandlung — ein Operator löst sie aus, ohne dass du selbst konvertierst:
"5" - 2,"" == 0,if (value).
Am Ende greifen beide auf dieselben Umwandlungsregeln zurück. Der Unterschied liegt nur darin, ob du oder die Sprache die Konvertierung angestoßen hat. Fast alle verwirrenden Ergebnisse in JavaScript — "5" + 1 === "51", [] == false, null == undefined — kommen daher, dass dich die implizite Coercion auf dem falschen Fuß erwischt.
Die Denkweise dahinter: Wenn du Number(...) oder String(...) schreibst, weißt du genau, was du willst. Lässt du es weg, hat jeder Operator seine eigene Meinung dazu, was passieren soll – und genau in diesen Meinungen stecken die Bugs.
Die drei Zieltypen bei der Typumwandlung
Type Coercion in JavaScript läuft immer auf einen von drei primitiven Typen hinaus: string, number oder boolean. (Es gibt zwar noch einen vierten, bigint, aber in den wird aus anderen Typen nie automatisch umgewandelt.) Alle weiteren Regeln ergeben sich daraus, welches Ziel der jeweilige Operator ansteuert.
String-Coercion ist die gnädige Variante – jeder Wert hat irgendeine String-Darstellung. Tückisch dabei: Objekte werden zu dem wenig hilfreichen "[object Object]" umgewandelt. Genau deshalb zeigt "user: " + user im Log so gut wie nie das, was du eigentlich sehen wolltest. Greif in solchen Fällen lieber zu JSON.stringify oder nutze Template-Literals mit konkreten Feldern.
Typumwandlung in Number
Bei der Umwandlung in eine Zahl ist JavaScript deutlich strenger. Der String muss tatsächlich wie eine Zahl aussehen, sonst bekommst du NaN:
Die eingeklammerten Überraschungen solltest du dir wirklich merken:
- Ein leerer String – und auch Strings, die nur aus Whitespace bestehen – werden zu
0, nicht zuNaN. nullwird zu0, aberundefinedwird zuNaN.- Ein leeres Array ergibt
0; ein Array mit genau einem Element wandelt dieses Element um; ein Array mit mehreren Elementen wird zuNaN.
Wenn du aus einem String mit zusätzlichen Zeichen eine Zahl herausziehen willst, greif zu parseInt oder parseFloat statt zu Number:
Übergib an parseInt immer die Basis (10). Ohne sie werden Strings, die mit "0x" beginnen, als Hex interpretiert – und das ist selten das, was du wolltest.
Umwandlung in Boolean
Die Umwandlung in einen Boolean ist die einfachste der drei Varianten. Eine kurze Liste von Werten wird zu false – alles andere ist true.
Die falsy-Werte sind:
false0,-0,0n""(leerer String)nullundefinedNaN
Mehr gibt es nicht. Jeder andere Wert – inklusive "false", "0", [] und {} – ist truthy.
Die Ergebnisse für leere Arrays und leere Objekte sind eine klassische Stolperfalle für alle, die von Python kommen – dort sind leere Collections nämlich falsy. In JavaScript sind sie dagegen truthy. Wenn du also wissen willst, ob ein Array leer ist, prüf das explizit mit arr.length === 0.
Die Boolean Coercion greift immer dann, wenn ein Wert dort auftaucht, wo ein Boolean erwartet wird: bei if (...), while (...), im Ternary-Operator ? : und bei den logischen Operatoren &&, || und !.
Der +-Operator ist ein Sonderfall
Die meisten arithmetischen Operatoren zwingen ihre Operanden in Zahlen um. Beim + läuft das anders: Sobald eine der beiden Seiten ein String ist, wird + zur String-Konkatenation. Nur wenn beide Seiten numerisch sind, findet eine echte Addition statt.
Die Auswertung läuft von links nach rechts. Bei 1 + 2 + "3" wird also zuerst 1 + 2 = 3 berechnet und dann 3 + "3" = "33". "1" + 2 + 3 fängt dagegen schon mit einem String an und bleibt dabei: erst "12", dann "123".
Genau deshalb ist das Zusammenbauen von Strings mit + so fehleranfällig. Template Literals haben dieses Problem nicht:
Das Template-Literal wertet count + 1 als eigenständigen numerischen Ausdruck aus und fügt erst danach das Ergebnis ein. Keine bösen Überraschungen durch implizite Typumwandlung.
Setze lieber auf explizite Typumwandlung
Wenn du einen Typ umwandeln musst, dann schreib es auch hin. Das kostet ein paar Zeichen mehr, nimmt aber jedem, der später den Code liest, jeden Zweifel:
Dasselbe gilt für Booleans. !!value funktioniert und ist durchaus verbreitet, aber Boolean(value) sagt unmissverständlich, was passiert:
Eine vernünftige Regel: In der Anwendungslogik setzt du auf explizite Typumwandlungen, während du die Kurzformen (+x, !!x) nur dort einsetzt, wo Knappheit zählt und die Absicht aus dem Kontext klar hervorgeht.
Der ==-Operator stützt sich stark auf Coercion
Die Vergleichsoperatoren sind die größte Quelle für Überraschungen bei der Typumwandlung. == wandelt vor dem Vergleich um, === nicht.
Jedes true oben ist das Ergebnis einer mehrstufigen Coercion-Kette, die kaum ein Entwickler auswendig herunterbeten kann. Und genau das ist das Problem – Code, der zufällig funktioniert, ist Code, der später bricht. Die vollständigen Vergleichsregeln schauen wir uns auf der nächsten Seite an; für den Moment gilt: standardmäßig === verwenden, und == nur für das eine sinnvolle Idiom x == null einsetzen (damit fängst du null und undefined in einem Rutsch ab).
Alles zusammengesetzt
Ein durchgearbeitetes Beispiel, das zeigt, wo Typumwandlung in JavaScript nützlich ist und wo sie dir Ärger macht:
Achtung beim zweiten Aufruf: Number("") liefert 0 zurück, nicht NaN — also gibt parsePrice("") ebenfalls 0 zurück, was für die meisten Anwendungsfälle wohl nicht das gewünschte Verhalten ist. Wenn leere Eingaben abgelehnt werden sollen, baust du besser eine explizite Prüfung ein:
Zu wissen, welche Werte zu 0 und welche zu NaN werden, ist genau die Art Detail, die dich vor fiesen Folgebugs bewahrt.
Was du mitnehmen solltest
- Type Coercion wandelt je nach Operator in String, Number oder Boolean um.
+zusammen mit einem String wird zur Konkatenation; jeder andere arithmetische Operator erzwingt eine Umwandlung in Number.- Die Liste der Falsy-Werte ist kurz und fest – präg sie dir ein. Alles andere ist truthy, auch
[]und{}. Number("")ist0,Number([])ist0,Number(null)ist0– aberNumber(undefined)istNaN. Genau solche Fälle sorgen in der Praxis für Bugs.- Setz lieber auf
Number(x),String(x)undBoolean(x)statt auf trickreiche implizite Typumwandlung. Dein zukünftiges Ich wird's dir danken.
Als Nächstes: Die Vergleichsoperatoren
Alles, was Coercion bei Vergleichen anstellt, steckt in ==. Die nächste Seite nimmt sich == vs. === vs. Object.is vor, zeigt das eine Idiom, bei dem == tatsächlich noch sinnvoll ist, und erklärt, warum Linter die lockere Variante standardmäßig anmeckern.
Häufig gestellte Fragen
Was ist Type Coercion in JavaScript?
Type Coercion bedeutet, dass JavaScript einen Wert automatisch in einen anderen Typ umwandelt – aus einer Zahl wird ein String, aus einem String eine Zahl, oder aus irgendetwas ein Boolean. Das passiert implizit, sobald Operatoren wie +, == oder if einen Wert sehen, der nicht zum erwarteten Typ passt, und explizit, wenn du selbst Number(x), String(x) oder Boolean(x) aufrufst.
Was ist der Unterschied zwischen impliziter und expliziter Coercion?
Bei expliziter Coercion rufst du die Konvertierungsfunktion bewusst auf: Number("42"), String(99), Boolean(value). Implizite Coercion passiert dagegen im Hintergrund, weil ein Operator die Umwandlung auslöst: "5" - 2 ergibt 3, aber "5" + 2 ergibt "52". Explizit ist lesbar und vorhersehbar – implizit ist der Grund für die meisten „Warum ist das auf einmal NaN?"-Bugs.
Wie wandle ich in JavaScript einen String in eine Zahl um?
Nimm Number("42") für eine strikte Konvertierung – bei ungültigen Strings kommt NaN raus. Wenn der String chaotischer ist und nur vorne eine Zahl steht, benutzt du parseInt("42px", 10) oder parseFloat("3.14em"). Der unäre +-Operator (+"42") macht dasselbe wie Number(), ist beim Überfliegen des Codes aber leicht zu übersehen.
Warum ergibt [] + [] einen leeren String?
[] + [] einen leeren String?Für zwei Arrays gibt es keine sinnvolle numerische +-Operation, also konvertiert JavaScript beide zu Strings. Arrays werden dabei per Komma zusammengefügt, und ein leeres Array wird zu "". Aus [] + [] wird also "" + "" – und das Ergebnis ist "". Netter Partytrick und gleichzeitig ein guter Grund, + niemals auf Nicht-Primitives loszulassen.