Wie schreibt man JavaScript richtig? Praktische Regeln für sauberen Code

Teilen

JavaScript ist überall. Auf jeder zweiten Webseite, in jeder App, in jedem Backend-System. Doch viele schreiben es so, als wäre es eine schnelle Lösung für ein Problem - und nicht eine echte Programmiersprache. Das Ergebnis? Code, der funktioniert, aber kaum zu warten ist. Der nach drei Monaten niemand mehr versteht. Der bei jedem Update neue Fehler bringt. Wenn du JavaScript richtig schreiben willst, geht es nicht um Frameworks oder neueste Syntax. Es geht um Grundlagen.

Benenne Dinge so, dass sie sagen, was sie tun

Ein schlechter Name ist der Anfang vom Ende. function x() oder let temp sind keine Namen. Sie sind Entschuldigungen. Ein guter Name sagt dir, was die Funktion macht, ohne dass du ihren Code lesen musst.

Statt:

function calc(a, b) {
  return a * b * 0.1;
}

schreibe:

function calculateTax(amount) {
  return amount * 0.1;
}

Das ist nicht nur lesbarer - es ist auch testbar. Wenn du später herausfindest, dass die Steuer auf 12 % steigt, dann änderst du den Wert. Nicht den Namen. Und jeder, der den Code liest, weiß sofort: Das ist die Steuerberechnung. Kein Rätselraten. Kein Kommentar nötig.

Vermeide globale Variablen - sie sind die größte Quelle für Bugs

Wenn du in der Konsole window.myData = "hello"; schreibst, dann hast du ein Problem. Nicht jetzt. Nicht heute. Aber in drei Monaten, wenn jemand anderes einen anderen Script-Tag einfügt und auch myData nutzt. Dann bricht alles.

JavaScript hat seit ES6 den const- und let-Operator. Nutze sie. Und halte Variablen so lokal wie möglich. Wenn du eine Funktion schreibst, die nur in einer bestimmten Datei gebraucht wird, dann exportiere sie nicht. Wenn du sie nicht exportierst, kann sie nicht von außen beschädigt werden.

Ein Beispiel:

// FALSCH - globale Variable
let userToken = "abc123";

function login() {
  userToken = fetchToken();
}

// RICHTIG - lokal und kontrolliert
function login() {
  const userToken = fetchToken();
  return userToken;
}

Jetzt ist userToken nur innerhalb von login() sichtbar. Kein anderer Teil des Codes kann ihn versehentlich überschreiben. Das ist nicht nur sicherer - es ist auch einfacher zu testen.

Schreibe kleine Funktionen - eine Aufgabe pro Funktion

Wenn eine Funktion mehr als 15 Zeilen hat, solltest du sie überprüfen. Nicht weil 15 eine magische Zahl ist - sondern weil jede Zeile, die du hinzufügst, die Wahrscheinlichkeit erhöht, dass etwas schiefgeht.

Ein Beispiel aus der Praxis:

// Zu groß - macht zu viel
function processOrder(order) {
  const total = order.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
  const tax = total * 0.19;
  const discount = order.hasCoupon ? total * 0.1 : 0;
  const finalTotal = total + tax - discount;
  const email = order.customer.email;
  sendEmail(email, `Ihre Bestellung ist fertig. Gesamt: ${finalTotal}€`);
  updateInventory(order.items);
  logOrder(order.id, finalTotal);
}

Dieser Code macht sieben Dinge. Wenn die E-Mail nicht gesendet wird, weißt du nicht, ob es an der E-Mail-Funktion liegt - oder an der Berechnung. Wenn du die Funktion aufteilst, wird es klar:

function calculateTotal(items) {
  return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}

function calculateTax(total) {
  return total * 0.19;
}

function calculateDiscount(total, hasCoupon) {
  return hasCoupon ? total * 0.1 : 0;
}

function calculateFinalTotal(total, tax, discount) {
  return total + tax - discount;
}

function sendOrderConfirmation(email, total) {
  sendEmail(email, `Ihre Bestellung ist fertig. Gesamt: ${total}€`);
}

function processOrder(order) {
  const total = calculateTotal(order.items);
  const tax = calculateTax(total);
  const discount = calculateDiscount(total, order.hasCoupon);
  const finalTotal = calculateFinalTotal(total, tax, discount);
  sendOrderConfirmation(order.customer.email, finalTotal);
  updateInventory(order.items);
  logOrder(order.id, finalTotal);
}

Jede Funktion macht jetzt genau eine Sache. Und wenn etwas schiefgeht, weißt du sofort, wo du suchen musst.

A house built on sand with clean code forming a stable foundation versus chaotic global variables.

Verwende keine if-else-Ketten - nutze Objekte oder Switch

Wenn du mehr als drei if-Abfragen hintereinander hast, ist dein Code schwer zu erweitern. Und er ist schwer zu testen.

Statt:

function getShippingCost(country) {
  if (country === "DE") return 5.99;
  if (country === "AT") return 6.99;
  if (country === "CH") return 8.99;
  if (country === "US") return 12.99;
  return 15.99;
}

sag:

const shippingRates = {
  DE: 5.99,
  AT: 6.99,
  CH: 8.99,
  US: 12.99
};

function getShippingCost(country) {
  return shippingRates[country] || 15.99;
}

Das ist kürzer. Es ist leichter zu erweitern. Und wenn du einen neuen Preis hinzufügst, musst du nicht einen neuen if-Block schreiben - du fügst einfach ein neues Schlüssel-Wert-Paar hinzu.

Das gleiche Prinzip gilt für Zustandswechsel. Wenn du eine Funktion hast, die je nach Zustand etwas anderes macht, nutze ein Objekt mit Funktionen:

const stateHandlers = {
  idle: () => startLoading(),
  loading: () => showSpinner(),
  success: () => hideSpinner(),
  error: () => showError()
};

function updateUI(state) {
  stateHandlers[state]?.();
}

Keine langen if-else-Labyrinthe. Nur klare Zuordnungen.

Schreibe Tests - nicht als Extra, sondern als Teil des Schreibens

Wer JavaScript schreibt, ohne zu testen, baut ein Haus auf Sand. Du denkst, du hast es getestet, weil du es im Browser geöffnet hast? Das ist kein Test. Das ist ein Klick.

Ein echter Test prüft, ob deine Funktion das tut, was sie soll - und ob sie das immer noch tut, wenn du etwas änderst. Mit Jest oder Vitest kannst du das in Minuten einrichten.

Beispiel:

// calculateTax.test.js
import { calculateTax } from './calculateTax';

test('berechnet 19% Steuer', () => {
  expect(calculateTax(100)).toBe(19);
});

test('gibt 0 zurück, wenn Eingabe 0 ist', () => {
  expect(calculateTax(0)).toBe(0);
});

Du schreibst den Test, bevor du die Funktion implementierst. Dann schreibst du die Funktion, bis der Test grün wird. Das ist Test-Driven Development. Es zwingt dich, klar zu denken. Und es verhindert, dass du in drei Monaten versehentlich eine Funktion kaputt machst, die du vergessen hast.

Vermeide asynchrone Code-Pyramiden - nutze async/await

Die alte Art, mit Asynchronität umzugehen, war mit .then()-Chains. Das führte zu etwas, das man "Pyramide des Schreckens" nennt:

fetch('/api/user')
  .then(response => response.json())
  .then(user => fetch(`/api/orders?userId=${user.id}`))
  .then(response => response.json())
  .then(orders => fetch(`/api/inventory?items=${orders.map(o => o.id).join(',')}`))
  .then(response => response.json())
  .then(inventory => console.log(inventory))
  .catch(error => console.error(error));

Das ist unlesbar. Und schwer zu debuggen.

Stattdessen:

async function loadUserData() {
  try {
    const userResponse = await fetch('/api/user');
    const user = await userResponse.json();
    
    const ordersResponse = await fetch(`/api/orders?userId=${user.id}`);
    const orders = await ordersResponse.json();
    
    const inventoryResponse = await fetch(`/api/inventory?items=${orders.map(o => o.id).join(',')}`);
    const inventory = await inventoryResponse.json();
    
    console.log(inventory);
  } catch (error) {
    console.error(error);
  }
}

Das ist fast wie normales, sequentielles Lesen. Und du kannst mit try/catch alle Fehler an einer Stelle fangen. Keine verschachtelten Callbacks. Kein Rätselraten.

Developer reviewing green test results while outdated code patterns burn in the background.

Formatiere deinen Code - und lass Tools das machen

Ein Code, der gut aussieht, ist ein Code, der leicht zu lesen ist. Und leicht zu lesen = leicht zu warten.

Nutze Prettier. Konfiguriere es einmal. Und lass es deinen Code automatisch formatieren. Egal ob du 2 Leerzeichen oder 4 verwendest - es ist egal. Hauptsache, es ist konsistent.

Und nutze ESLint. Es findet Dinge, die du nicht siehst: ungenutzte Variablen, falsche Vergleiche, versteckte Typenfehler. Es sagt dir: Hey, du hast hier eine Variable deklariert, aber nie benutzt. Oder: Du vergleichst einen String mit einer Zahl mit == - das ist riskant.

Ein guter ESLint-Setup für Anfänger:

{
  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
  "rules": {
    "no-var": "error",
    "prefer-const": "error",
    "eqeqeq": ["error", "always"],
    "no-console": "warn"
  }
}

Das sorgt dafür, dass du var nicht mehr verwendest, dass du const und let richtig nutzt, und dass du === statt == verwendest. Das sind kleine Dinge - aber sie verhindern große Probleme.

Verstehe, dass JavaScript nicht perfekt ist - und arbeite damit

JavaScript hat seine Macken. typeof null === "object". [] + [] === "". 0.1 + 0.2 !== 0.3. Das ist nicht deine Schuld. Aber du musst es wissen.

Wenn du mit Zahlen rechnest, nutze Number.toFixed() oder Bibliotheken wie decimal.js. Wenn du Arrays vergleichst, nutze JSON.stringify() nur für einfache Fälle - oder schreibe eine eigene Vergleichsfunktion. Wenn du mit DOM-Elementen arbeitest, nutze querySelector statt getElementById - es ist flexibler und moderner.

Die beste JavaScript-Praxis ist nicht, alles zu perfektionieren. Sondern: Wissen, wo die Fallen liegen - und sie umgehen.

Was du nicht brauchst: Frameworks als Ersatz für Grundlagen

React, Vue, Svelte - sie sind großartig. Aber sie ersetzen keine guten JavaScript-Kenntnisse. Wenn du nicht verstehst, wie Events funktionieren, wie Closure arbeiten, oder warum this manchmal nicht das ist, was du denkst - dann wirst du mit jedem Framework scheitern.

Ein Framework macht dich nicht besser. Es macht nur, was du ihm sagst - schneller. Aber wenn du ihm falsche Anweisungen gibst, dann macht es sie schneller falsch.

Wenn du JavaScript richtig schreiben willst, dann lerne zuerst JavaScript. Dann lerne ein Framework. Nicht umgekehrt.

Über den Autor

Sonja Meierhof

Sonja Meierhof

Ich bin Sonja Meierhof und ich habe eine Leidenschaft für Entwicklung. Als Expertin in meinem Feld habe ich zahlreiche Projekte in verschiedenen Programmiersprachen umgesetzt. Ich liebe es, mein Wissen durch das Schreiben von Fachartikeln zu teilen, besonders im Bereich Softwareentwicklung und innovative Technologien. Stetig arbeite ich daran, meine Fähigkeiten zu erweitern und neue Programmierkonzepte zu erforschen.