Der Spickzettel zur zweiten Hälfte des Seminars JavaScript Grundlagen & Modernes ECMAScript: alles, was um die Sprache herum zum Arbeiten gehört. Die Sprache selbst — Typen, Datenstrukturen, Closures — steht auf dem ersten Blatt: JavaScript Sprachkern.
Maßgeblich bleibt die Node.js-Dokumentation für Node-eigene APIs und MDN für die Sprache. Dieses Blatt trifft die Auswahl und ersetzt weder Referenz noch Seminar.
Debuggen: die Schrittbefehle
| Befehl | Wirkung |
|---|---|
| Step Over | führt die Zeile aus, ohne in Funktionen zu springen |
| Step Into | springt in den Aufruf hinein |
| Step Out | beendet die aktuelle Funktion, zurück zum Aufrufer |
| Continue | läuft bis zum nächsten Haltepunkt |
Der Aufrufstapel zeigt den Weg bis zur aktuellen Zeile — bei tiefen Fehlern die wichtigste Ansicht, und die, die am häufigsten ignoriert wird. Der Haltepunkt gehört vor die interessante Zeile, nicht dahinter.
Modul: Problemlösung und Debugging
Testen: Begriffe und Werkzeuge
| Begriff | Bedeutung |
|---|---|
| Testfall | ein konkretes Szenario mit erwartetem Ergebnis |
| Testsuite | eine Gruppe zusammengehörender Testfälle |
| Zusicherung | die Prüfung, ob etwas dem Erwarteten entspricht |
| Abdeckung | Anteil des Codes, den die Tests ausgeführt haben |
| Werkzeug | Einordnung |
|---|---|
| Jest | seit Jahren verbreitet, in vielen Bestandsprojekten |
| Vitest | in modernen Projekten üblich, besonders mit Vite |
node:test | in Node.js eingebaut, ohne zusätzliche Abhängigkeit |
Die Schreibweise ist nahezu identisch — describe, it, expect:
import { describe, it, expect } from "vitest";
describe("istBefuellt", () => {
it("lehnt eine leere Zeichenkette ab", () => {
expect(istBefuellt("")).toBe(false);
});
});
Hohe Abdeckung mit schwachen Zusicherungen beweist nichts; sie ist kein Qualitätsziel für sich.
Modul: JavaScript testen
Asynchron: die drei Muster
| Muster | Idee |
|---|---|
| Callback | eine Funktion, die später aufgerufen wird |
| Promise | ein Platzhalter für ein Ergebnis, das noch aussteht |
async/await | asynchroner Code, der sich wie synchroner liest |
| Zustand eines Promise | Bedeutung |
|---|---|
| ausstehend | die Operation läuft noch |
| erfüllt | sie war erfolgreich, ein Wert liegt vor |
| abgelehnt | sie ist gescheitert, ein Fehler liegt vor |
Alle drei Muster existieren nebeneinander — im Bestand trifft man auf jedes.
Eine async-Funktion liefert immer ein Promise, auch wenn im Rumpf nichts
Asynchrones passiert. Synchrones try/catch greift nur zusammen mit await.
Modul: Asynchrones JavaScript
Welcher Promise-Kombinator wann
| Aufruf | Verhalten |
|---|---|
Promise.all | alle müssen gelingen, bricht beim ersten Fehler ab |
Promise.allSettled | wartet auf alle, meldet je Vorgang den Ausgang |
Promise.any | der erste Erfolg genügt, Fehler werden ignoriert |
Promise.race | der erste entschiedene Vorgang zählt, egal wie |
Promise.try | startet eine Kette aus möglicherweise synchronem Code |
Die Reihenfolge der Ergebnisse bei all entspricht der Eingabe, nicht der
Fertigstellung. Unabhängige Aufrufe gehören parallel gestartet statt einzeln
awaitet — aufeinander aufbauende dagegen nicht.
HTTP: fetch prüft nichts von allein
const antwort = await fetch(url);
if (!antwort.ok) throw new Error(`HTTP ${antwort.status}`);
const daten = await antwort.json();
fetch lehnt nur bei Netzwerkfehlern ab — ein 404 kommt als ganz normale
Antwort an. Wer auf einen Fehler wartet, wartet vergebens. Die Struktur der
Antwort ist ebenfalls nicht garantiert und gehört geprüft.
Modul: Promises, HTTP-Anfragen und Events
Module: Exportarten und Pfade
| Art | Passend, wenn … |
|---|---|
| benannt | das Modul mehrere verwandte Funktionen anbietet |
| Standard | das Modul genau einen Hauptwert hat |
| beides gemischt | möglich, aber selten hilfreich |
Benannte Exporte sind der Normalfall — im Importierenden ist sofort sichtbar, was
benutzt wird. Für ES-Module gilt: "type": "module" in der package.json, die
Dateiendung im Importpfad ist nötig, relative Pfade beginnen mit einem Punkt, und
eingebaute Module tragen das Präfix node:. JSON lässt sich direkt importieren —
mit Attribut:
import beete from "./beete.json" with { type: "json" };
Modul: Module, Pakete und Projektstruktur
Projektdateien: was wohin gehört
| Datei oder Ordner | Umgang |
|---|---|
package.json | in die Versionsverwaltung |
package-lock.json | ebenfalls — sie macht Installationen reproduzierbar |
node_modules/ | nicht einchecken, nicht von Hand ändern |
Auf einem anderen Rechner stellt npm install den Stand aus beiden Dateien
wieder her. Geschnitten wird nach Zuständigkeit, nicht nach Dateityp: eine Datei
für den Dateizugriff, eine für die Prüfung, eine für die Darstellung, eine für
die Fachlogik — und ein Einstiegspunkt, der nur koordiniert.
Kommandozeilenargumente nicht von Hand zählen, sondern benannt auslesen:
import { parseArgs } from "node:util";
const { values } = parseArgs({
options: { name: { type: "string", short: "n" } },
});
Modul: Module, Pakete und Projektstruktur
Daten: Herkunft, Datenbank, SQL
| Herkunft | Passend, wenn … |
|---|---|
| statischer Import | die Daten fester Bestandteil des Projekts sind |
| Datei zur Laufzeit | der Pfad variabel ist oder sich der Inhalt ändert |
| HTTP-Antwort | die Daten von einem anderen System kommen |
Am Ende entstehen in allen drei Fällen gewöhnliche JavaScript-Objekte — nur Herkunft und Fehlerquellen unterscheiden sich.
| Datenbank | JavaScript |
|---|---|
| Spalten in Unterstrich-Schreibweise | Eigenschaften in camelCase |
| Wahrheitswerte als 0 und 1 | true und false |
| Zeilen als Ergebnis | Objekte im Programm |
Die Umsetzung zwischen beiden Welten gehört an eine Stelle. Und Abfragen werden parametrisiert, nie zusammengesetzt:
const nachArt = db.prepare("SELECT * FROM beete WHERE art = ?");
const treffer = nachArt.all(eingabe);
Modul: Dateizugriff, Datenaustausch und Datenbanken
Sauberer Code: wer wofür zuständig ist
| Werkzeug | Aufgabe |
|---|---|
| ESLint | meldet mögliche Fehler und Projektregeln |
| Prettier | vereinheitlicht Einrückung, Umbrüche, Anführungszeichen |
| Engine | akzeptiert oder verwirft — mehr nicht |
Der Linter sagt „das sieht nach einem Fehler aus”, der Formatierer beendet die
Stildiskussion. Beim Lesen fremden Codes: bei der package.json anfangen, die
Skripte mitlesen, den Datenfluss Datei für Datei verfolgen — und alte Muster
nicht ungefragt modernisieren.
Modul: Sauberer Code und fremden Code lesen
Typische Fallen
- Ein 404 ist kein Fehler für
fetch. Ohneantwort.okläuft der Fehlerfall als Erfolg weiter. awaitvergessen — und man arbeitet mit einem Promise statt mit dem Wert.catchweggelassen erzeugt eine unbehandelte Ablehnung.finallyläuft auch im Fehlerfall — es ist kein Erfolgspfad.- Kein Zeitlimit lässt eine hängende Anfrage nie enden.
readFileohne Kodierungsangabe liefert einen Puffer statt Text.- Relative Pfade hängen davon ab, aus welchem Ordner gestartet wurde —
besser über
import.meta.urlaufbauen. - SQL aus Zeichenketten zusammensetzen, auch nur ein einziges Mal: das ist die Einladung zur SQL-Injection. Eine Eingabeprüfung ersetzt das nicht.
node_moduleseinchecken oder diepackage-lock.jsonweglassen — beides fällt erst auf dem zweiten Rechner auf.- ES-Module und CommonJS in einer Datei mischen oder das
node:-Präfix weglassen. - Ereignisnamen vertippen: Es passiert schlicht nichts, keine Meldung.
- Testdateien so benennen, dass das Werkzeug sie nicht findet — oder das
Testskript in der
package.jsonvergessen. - Nur den Normalfall testen und den Fall
0auslassen, weil er wie ein leerer Wert aussieht. - Linter-Meldungen pauschal abschalten, statt sie zu beheben.