Menu

Type Coercion in JavaScript: Implizit vs. Explizit

Wie JavaScript Werte zwischen Typen umwandelt – die impliziten Regeln, die für Verwirrung sorgen, die expliziten Konvertierungen, die du bevorzugen solltest, und wann beides greift.

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.

index.js
Output
Click Run to see the output here.

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.

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

Die eingeklammerten Überraschungen solltest du dir wirklich merken:

  • Ein leerer String – und auch Strings, die nur aus Whitespace bestehen – werden zu 0, nicht zu NaN.
  • null wird zu 0, aber undefined wird zu NaN.
  • Ein leeres Array ergibt 0; ein Array mit genau einem Element wandelt dieses Element um; ein Array mit mehreren Elementen wird zu NaN.

Wenn du aus einem String mit zusätzlichen Zeichen eine Zahl herausziehen willst, greif zu parseInt oder parseFloat statt zu Number:

index.js
Output
Click Run to see the output here.

Ü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:

  • false
  • 0, -0, 0n
  • "" (leerer String)
  • null
  • undefined
  • NaN

Mehr gibt es nicht. Jeder andere Wert – inklusive "false", "0", [] und {} – ist truthy.

index.js
Output
Click Run to see the output here.

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.

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

Dasselbe gilt für Booleans. !!value funktioniert und ist durchaus verbreitet, aber Boolean(value) sagt unmissverständlich, was passiert:

index.js
Output
Click Run to see the output here.

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.

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

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:

index.js
Output
Click Run to see the output here.

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("") ist 0, Number([]) ist 0, Number(null) ist 0 – aber Number(undefined) ist NaN. Genau solche Fälle sorgen in der Praxis für Bugs.
  • Setz lieber auf Number(x), String(x) und Boolean(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?

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.

Lerne mit Coddy zu programmieren

LOS GEHT'S