EMZETT.
Login

Kurz: Guter JavaScript-Code ist lesbar, vorhersagbar und vermeidet bekannte Stolperfallen.

Teil des Kurses JavaScript

Kapitel 38 von 40 im Kurs JavaScript. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Guter JavaScript-Code ist lesbar, vorhersagbar und vermeidet bekannte Stolperfallen.

Lesbarkeit

  • Sprechende Namen: anzahlKunden statt n, istAktiv statt flag. Funktionen sind Verben (berechneSumme), Booleans lesen sich wie Fragen (hatZugriff)
  • Kleine Funktionen: eine Funktion, eine Aufgabe
  • Frühe Rückgabe statt tiefer Verschachtelung
  • Keine magischen Zahlen: const MAX_VERSUCHE = 3 statt einer losen 3
  • Kommentare erklären das Warum, nicht das Was
// Schlecht
function f(a) { if (a) { if (a.length > 0) { if (a[0] > 5) { return true; } } } return false; }
 
// Besser
const MIN_WERT = 5;
function ersterWertIstGross(liste) {
  if (!liste?.length) return false;
  return liste[0] > MIN_WERT;
}
console.log(f([9]), ersterWertIstGross([9]), ersterWertIstGross([]));

Ausgabe:

true true false

Empfohlene Gewohnheiten

TueStatt
const / letvar
=====
Template-StringsText mit + zusammenkleben
map/filter/reduceSchleifen, die Arrays aufbauen
?. und ??lange &&-Ketten
async/awaitverschachtelte Callbacks
Module (import)globale Variablen

Häufige Fallen

1. Typumwandlung

console.log("5" + 1, "5" - 1, [] + {}, [1, 2] + [3]);
console.log(0.1 + 0.2 === 0.3, 9007199254740993);
console.log([10, 9, 1].sort());
console.log(parseInt("08"), parseInt("0x1f"), Number(""), Number(" "), Number(null), Number(undefined));

Ausgabe:

51 4 [object Object] 1,23
false 9007199254740992
[ 1, 10, 9 ]
8 31 0 0 0 NaN

2. this verloren

const objekt = { name: "Mia", sagHallo() { return "Hallo " + this?.name; } };
const lose = objekt.sagHallo;
console.log(objekt.sagHallo(), "|", lose());
console.log(lose.call({ name: "Tom" }), "|", lose.bind(objekt)());

Ausgabe:

Hallo Mia | Hallo undefined
Hallo Tom | Hallo Mia

3. Veränderliche geteilte Daten

const a = { liste: [1, 2] };
const b = { ...a };               // flache Kopie: liste wird geteilt!
b.liste.push(3);
console.log(a.liste);
const c = structuredClone(a);
c.liste.push(4);
console.log(a.liste, c.liste);
 
function f(x = []) { x.push(1); return x; }      // neue Liste pro Aufruf (anders als in Python)
console.log(f(), f());

Ausgabe:

[ 1, 2, 3 ]
[ 1, 2, 3 ] [ 1, 2, 3, 4 ]
[ 1 ] [ 1 ]

4. Vergessene await

const hole = async () => 42;
async function main() {
  const falsch = hole();           // Promise statt Wert
  const richtig = await hole();
  console.log(typeof falsch, falsch instanceof Promise, richtig);
  [1, 2, 3].forEach(async x => { await null; });   // forEach wartet nicht
}
main();

Ausgabe:

object true 42

5. Gleichheit von Objekten

console.log({} === {}, [] === [], [1] == 1, NaN === NaN, Object.is(NaN, NaN));
console.log(JSON.stringify({ a: 1 }) === JSON.stringify({ a: 1 }));
console.log(structuredClone({ a: [1] }).a !== undefined);

Ausgabe:

false false true false true
true
true

6. Schleifen und Closures mit var

Siehe Kapitel Gültigkeitsbereich: Nutze let/const in Schleifen.

7. Unveränderliches bevorzugen

Funktionen, die ihre Eingaben nicht verändern, sind leichter zu verstehen. Nutze toSorted, toReversed, Spread und structuredClone, statt Parameter zu mutieren.

Sicherheit im Web-Code

  • XSS: Setze nie ungeprüfte Nutzereingaben per innerHTML ein; benutze textContent oder baue Elemente mit createElement
  • Keine Geheimnisse im Frontend: API-Schlüssel und Passwörter im Browsercode sind für alle sichtbar
  • Eingaben nie vertrauen: Prüfe sie am Server, auch wenn der Browser sie schon geprüft hat
  • eval() und new Function() nicht für Nutzereingaben verwenden
  • Abhängigkeiten aktuell halten (npm audit)

Leistung

  • Nur messen, was langsam ist, nicht raten (console.time, Performance-Tab)
  • DOM-Zugriffe bündeln, nicht in jeder Schleife innerHTML += ausführen
  • Große Listen mit Virtualisierung oder Paginierung anzeigen
  • Ereignisse mit Debounce/Throttle drosseln
  • Ressourcen nachladen, wenn sie gebraucht werden (import(), loading="lazy")

Barrierefreiheit

  • Native Elemente (button, a, input) statt div mit Klick-Listener
  • Alle Funktionen per Tastatur erreichbar machen
  • Dynamische Änderungen mit aria-live oder role="status" ankündigen
  • Fokus beim Öffnen und Schließen von Dialogen bewusst setzen

Merke

  • Sprechende Namen, kleine Funktionen, frühe Rückgabe
  • const/let, ===, Template-Strings, async/await
  • Fallen: Typumwandlung, this, flache Kopien, vergessene await, Objektgleichheit
  • Eingaben nie ungeprüft in innerHTML; keine Geheimnisse im Frontend
  • Erst messen, dann optimieren

Übungsaufgabe

Gehe ein älteres Skript durch und ersetze var, == und verschachtelte Bedingungen durch moderne Muster. Schreibe zu jeder Änderung einen Satz, warum.

Quiz zur Selbstkontrolle

== 1 wahr?

  • == wandelt Typen vorher um (richtig)
  • Arrays sind Zahlen
  • Es ist ein Fehler
  • Weil [1] ein Objekt ist

Weiter im Kurs

Zurück: Werkzeuge: Linter, Formatter, TypeScript

Weiter: Projekt: Eine Aufgabenliste

Alle Kapitel: JavaScript im Überblick