Die if-Anweisung ist die einfachste Form bedingter Ausführung in JavaScript — ein Block läuft nur, wenn ein Ausdruck truthy ist. Daneben gibt es den Ternary-Operator bedingung ? a : b als Expression-Variante, die einen Wert liefert statt eines Effekts. Beide haben dieselbe semantische Wurzel — die ToBoolean-Coercion — und unterscheiden sich nur in der syntaktischen Form: Statement vs. Expression. Dieser Artikel zeigt die Mechanik beider Formen, klärt das Truthy/Falsy-Verhalten als praktische Grundlage und gibt Faustregeln, wann eine Form der anderen vorzuziehen ist.
if als Statement
Eine if-Anweisung führt einen Block aus, wenn der Ausdruck in den Klammern zu einem truthy-Wert evaluiert. Optional folgen else if-Zweige und ein abschließendes else. Die Reihenfolge ist signifikant — die Engine prüft von oben nach unten und nimmt den ersten passenden Zweig.
const alter = 17;
if (alter >= 18) {
console.log('Volljährig');
} else if (alter >= 16) {
console.log('Begleitetes Fahren möglich');
} else {
console.log('Minderjährig');
}Begleitetes Fahren möglichDie geschweiften Klammern sind technisch optional, wenn nur eine einzige Anweisung folgt — aber das ist eine berüchtigte Falle. Konsistent setzen, immer.
Klammern weglassen — und warum es eine schlechte Idee ist
JavaScript erlaubt if (bed) anweisung; ohne Block, wenn nur eine Anweisung folgt. Das macht den Code kürzer, aber gefährlich beim späteren Hinzufügen einer zweiten Zeile.
let zugriff = false;
// Vermeintlich harmlose Version
if (false)
zugriff = true;
console.log('Zugriff erteilt'); // läuft IMMER — gehört nicht zum if!
console.log(zugriff); // falseZugriff erteilt
falseLinter wie ESLint haben dafür die Regel curly — sie zwingt zur Klammer-Form und eliminiert die Falle. Praktisch jede Style-Guide (Airbnb, StandardJS, Google) macht Klammern zur Pflicht.
Truthy und Falsy — der Coercion-Aspekt
Bevor if den Block ausführt, wendet die Engine ToBoolean auf den Ausdruck an. Die Liste der falsy-Werte ist klein und auswendig zu wissen: false, 0, -0, 0n, '', null, undefined, NaN. Alles andere ist truthy — auch '0' (nicht-leerer String), 'false', [] (leeres Array!) und {} (leeres Objekt).
const werte = [false, 0, '', null, undefined, NaN, [], {}, '0', 'false'];
for (const v of werte) {
console.log(JSON.stringify(v), '→', Boolean(v));
}false → false
0 → false
"" → false
null → false
undefined → false
null → false
[] → true
{} → true
"0" → true
"false" → trueNaN wird von JSON.stringify zu null — daher tauchen zwei null → Zeilen auf. Die Klassifikation selbst bleibt davon unberührt.
Ternary-Operator — bedingung ? a : b
Der Ternary-Operator ist die Expression-Variante der bedingten Logik. Er evaluiert die Bedingung, liefert dann entweder den Wert links oder den Wert rechts vom Doppelpunkt. Damit lässt sich er an jeder Stelle einsetzen, an der ein Ausdruck erwartet wird — in Zuweisungen, return-Statements, Argumenten, JSX/Template-Literals.
const alter = 20;
// Zuweisung — der Klassiker
const status = alter >= 18 ? 'Erwachsen' : 'Minderjährig';
console.log(status); // 'Erwachsen'
// In Template-Literal
console.log(`Du bist ${alter >= 18 ? 'volljährig' : 'minderjährig'}.`);
// Im return einer Funktion
function preis(mitglied) {
return mitglied ? 7.50 : 9.90;
}
console.log(preis(true)); // 7.5Erwachsen
Du bist volljährig.
7.5Mit if/else ginge das gleiche, aber als Statement — also nur über eine vorab deklarierte Variable oder einen separaten Funktions-Body. Der Ternary spart genau dieses Zwischen-Konstrukt ein.
Verschachtelte Ternaries — Vorsicht
Mehrere Ternaries lassen sich ineinander verschachteln. Die Sprache erlaubt das problemlos, aber Lesbarkeit verschlechtert sich schnell.
const alter = 17;
// Lesbar, weil sauber eingerückt
const stufe =
alter < 6 ? 'Kindergarten' :
alter < 14 ? 'Schulkind' :
alter < 18 ? 'Jugendlich' :
'Erwachsen';
console.log(stufe); // 'Jugendlich'
// Schwer lesbar — alles in einer Zeile
const kurz = alter < 6 ? 'KG' : alter < 14 ? 'SK' : alter < 18 ? 'JU' : 'ER';
console.log(kurz); // 'JU'Jugendlich
JUDie saubere mehrzeilige Form mit eingerückten Doppelpunkten ist für 3-4 Stufen noch akzeptabel — bei mehr Zweigen ist eine Lookup-Tabelle oder switch die bessere Wahl.
Wann if, wann Ternary?
Die Faustregel ist die Unterscheidung Effekt vs. Wert:
if/else: wenn der Block eine Aktion ausführt (Logging, Mutation, Side-Effect, mehrere Statements).- Ternary: wenn die Bedingung einen Wert liefert, der weiterverwendet wird.
// Gut: if für Aktion
function loginVersuch(passwort) {
if (passwort === 'geheim') {
console.log('Eingeloggt');
// weitere Aktionen ...
} else {
console.log('Falsch');
}
}
loginVersuch('geheim');
// Gut: Ternary für Wert
function gruss(name) {
return `Hallo ${name ?? 'Gast'}, ${new Date().getHours() < 12 ? 'guten Morgen' : 'guten Tag'}!`;
}
console.log(gruss('Anna'));Eingeloggt
Hallo Anna, guten Tag!Wer Ternaries für Side-Effects nutzt — etwa bedingung ? log('a') : log('b'); — schreibt damit syntaktisch eine Expression, die als Statement verwendet wird. Funktional ok, stilistisch fast immer ein Warnsignal: ein if/else hätte den Effekt klarer gemacht.
Short-Circuit-Operatoren als Alternative
&& und || sind keine Bedingungs-Operatoren im strengen Sinn — sie liefern einen der Operanden zurück und nutzen Short-Circuit-Evaluation. In der Praxis tauchen sie häufig in if-ähnlichen Kontexten auf.
const user = { name: 'Anna' };
// && — wenn truthy, dann ausführen
user && console.log(user.name); // 'Anna'
// || — Default-Wert wenn falsy
const eingabe = '';
const ausgabe = eingabe || 'Gast';
console.log(ausgabe); // 'Gast'
// ?? — Nullish (nur null/undefined), nicht 0/''/false
const port = 0;
console.log(port || 8080); // 8080 — || behandelt 0 als falsy
console.log(port ?? 8080); // 0 — ?? unterscheidet 0Anna
Gast
8080
0Für den Default-Wert-Pattern ist ?? (Nullish Coalescing) seit ES2020 fast immer die bessere Wahl als ||, weil es nicht in die Truthy/Falsy-Falle bei 0, '', false läuft.
Early Return — verschachtelte ifs vermeiden
Eine der wirksamsten Lesbarkeits-Techniken ist Early Return: statt geschachtelter if-Blöcke prüft man Sonderfälle zuerst und verlässt die Funktion. Der Hauptpfad bleibt linear und flach.
// Verschachtelt — schwer lesbar
function rabattAlt(user) {
if (user) {
if (user.aktiv) {
if (user.mitglied) {
return 20;
} else {
return 10;
}
} else {
return 0;
}
} else {
return 0;
}
}
// Mit Early Returns — flach und linear
function rabattNeu(user) {
if (!user) return 0;
if (!user.aktiv) return 0;
if (!user.mitglied) return 10;
return 20;
}
console.log(rabattNeu({ aktiv: true, mitglied: true })); // 20
console.log(rabattNeu({ aktiv: false })); // 020
0Die zweite Form heißt auch Guard Clauses. Sie reduziert die kognitive Last, weil jeder Zweig sofort ein Ergebnis produziert — der Leser muss nicht zurück durch verschachtelte Blöcke springen, um zu wissen, was wann zutrifft.
Komma-Operator in Bedingungen
Der Komma-Operator wertet alle Ausdrücke aus und liefert den letzten zurück. In if-Bedingungen ist das zu 99 % ein Anti-Pattern — aber es taucht in Kompressionswettbewerben und Code-Golf auf.
let zaehler = 0;
// Komma in Bedingung: alle drei Ausdrücke werden ausgewertet,
// entscheidend ist der LETZTE — hier bedingung
if (zaehler++, zaehler++, zaehler > 1) {
console.log('truthy, zaehler =', zaehler);
}
// → 'truthy, zaehler = 2'
// Praktisch lesbarer
zaehler = 0;
zaehler++;
zaehler++;
if (zaehler > 1) console.log('zaehler =', zaehler);truthy, zaehler = 2
zaehler = 2Der Komma-Operator hat legitime Anwendungen im for-Initializer (for (let i = 0, j = 10; ...)) — in if-Bedingungen praktisch nie.
Lookup-Tabelle als Ersatz für lange if-Ketten
Sobald eine if/else if-Kette mehr als drei Zweige hat und auf diskrete Werte vergleicht, ist eine Object- oder Map-basierte Lookup-Tabelle fast immer lesbarer.
// Klassisch
function statusText(code) {
if (code === 200) return 'OK';
else if (code === 404) return 'Not Found';
else if (code === 500) return 'Server Error';
else return 'Unbekannt';
}
// Lookup
const stati = {
200: 'OK',
404: 'Not Found',
500: 'Server Error',
};
const statusText2 = code => stati[code] ?? 'Unbekannt';
console.log(statusText2(404)); // 'Not Found'
console.log(statusText2(418)); // 'Unbekannt'Not Found
UnbekanntDie Lookup-Variante skaliert besser: neue Codes hinzufügen heißt eine Zeile im Objekt — keine neue if-Zeile mit Re-Check der Reihenfolge.
Interessantes
if als Statement, Ternary als Expression — derselbe Branch in zwei Formen
Beide nutzen intern dieselbe ToBoolean-Coercion auf den Bedingungs-Ausdruck. Die einzigen echten Unterschiede: if ist ein Statement (führt Anweisungen aus, hat keinen Wert), Ternary ist eine Expression (liefert einen Wert, kann nichts ausführen ohne Side-Effect). Wahl ergibt sich aus dem Verwendungs-Kontext — eine Zuweisung erwartet eine Expression, ein Code-Block erwartet ein Statement.
if (x = y) ist eine Zuweisung — keine Vergleich
Klassische C-Falle, die auch in JavaScript zuschlägt. if (x = y) weist y an x zu und prüft dann den Wert von x. ESLint warnt mit der Regel no-cond-assign. Wenn die Zuweisung in der Bedingung wirklich gewollt ist, doppelte Klammern erzwingen die Absicht: if ((x = y)).
leeres Array [] und leeres Objekt {} sind truthy
Ein gängiges Missverständnis — in vielen Sprachen wären beide „falsy" als leere Container. JavaScript hat hier eine harte Regel: jeder Object-Referenz ist truthy, egal ob leer oder voll. Wer prüfen will, ob ein Array Elemente hat, schreibt arr.length > 0 (oder kurz arr.length, was bei 0 falsy ist).
document.all ist truthy, aber == false — der historische Ausreißer
Das alte document.all aus DOM-Level-0 ist der einzige offizielle Sonderfall in der Spec: typeof document.all liefert 'undefined', Boolean(document.all) liefert false. Das ist eine bewusste Web-Compat-Krücke aus den frühen 2000ern. In modernem Code irrelevant, aber Quiz-tauglich.
if (obj && obj.eigenschaft) wird durch Optional Chaining überflüssig
Vor ES2020 war if (obj && obj.eigenschaft) ... der Standard-Guard gegen null/undefined-Zugriffe. Mit ?. reicht if (obj?.eigenschaft) ... — kürzer und mit identischer Semantik. Die alte Form ist nicht „falsch", aber neue Codebasen sollten das Optional Chaining nutzen.
Ternary-Returns: return cond ? a : b ist idiomatisch
Funktionen, die einen von zwei Werten zurückgeben, sind mit return cond ? a : b; meist kürzer und lesbarer als ein 4-zeiliges if/else mit zwei return-Statements. Voraussetzung: die beiden Werte sind echte Werte, keine ganzen Blöcke mit weiteren Anweisungen.
Klammern in Ternary-Ketten: assoziativ rechts
Der Ternary-Operator ist rechts-assoziativ: a ? b : c ? d : e wird gelesen als a ? b : (c ? d : e). Das ergibt die übliche Kette „if-elseif-else" als Expression. Linke Klammerung — (a ? b : c) ? d : e — ist möglich, aber selten gewollt.
JSX/Template-Literals: Ternary ist die einzige Branch-Form
In JSX oder im ${...}-Slot eines Template-Literals darf nur eine Expression stehen — kein if. Ternary ist daher die Standard-Branch-Form für inline-Markup-Bedingungen: . Bei mehr als zwei Zweigen lohnt das Auslagern in eine Funktion.Status: ${ok ? 'aktiv' : 'inaktiv'}
Weiterführende Ressourcen
Externe Quellen
- if...else – MDN
- Conditional (ternary) operator – MDN
- Truthy – MDN Glossary
- Falsy – MDN Glossary
- The if Statement – ECMAScript Spec