Funktionale Programmierung in JavaScript: Von der Theorie zur Praxis
Funktionale Programmierung (FP) ist ein Paradigma, das Berechnungen als Auswertung mathematischer Funktionen betrachtet und Zustandsänderungen sowie veränderliche Daten vermeidet. Im modernen JavaScript, insbesondere in der Node.js-Umgebung, wird der funktionale Ansatz aufgrund seiner Vorhersagbarkeit, Testbarkeit und Modularität immer beliebter. In diesem Artikel werden wir die wichtigsten Konzepte der FP erläutern und zeigen, wie man sie in realen Projekten anwendet.
1. Reine Funktionen und das Fehlen von Seiteneffekten
Eine reine Funktion ist eine Funktion, die:
- Für dieselben Argumente immer dasselbe Ergebnis zurückgibt (Determinismus).
- Keine Seiteneffekte verursacht (keine externen Variablen ändert, keine Daten ausgibt, nicht auf das Dateisystem zugreift).
Beispiel einer reinen Funktion:
// Reine Funktion: addiert zwei Zahlenconst add = (a, b) => a + b;
console.log(add(2, 3)); // 5console.log(add(2, 3)); // 5 — immer gleichBeispiel einer unreinen Funktion:
let counter = 0;const increment = () => { counter++; // Seiteneffekt: ändert eine externe Variable return counter;};
console.log(increment()); // 1console.log(increment()); // 2 — Ergebnis unterschiedlichIn der funktionalen Programmierung streben wir danach, nur reine Funktionen zu schreiben. Das macht den Code leichter test- und debugbar.
2. Unveränderlichkeit von Daten (Immutability)
Unveränderlichkeit bedeutet, dass Daten nach ihrer Erstellung nicht geändert werden. Anstatt ein bestehendes Objekt zu verändern, erstellen wir eine neue Kopie mit den gewünschten Änderungen. In JavaScript verwendet man dafür oft den Spread-Operator (...) oder die Methode Object.assign.
Beispiel für eine unveränderliche Aktualisierung eines Objekts:
const user = { name: 'Alice', age: 30 };
// Schlecht: Mutationuser.age = 31;
// Gut: neues Objekt erstellenconst updatedUser = { ...user, age: 31 };
console.log(user); // { name: 'Alice', age: 30 }console.log(updatedUser); // { name: 'Alice', age: 31 }Für Arrays verwenden wir ebenfalls unveränderliche Methoden:
const numbers = [1, 2, 3];
// Mutation (schlecht)numbers.push(4);
// Unveränderlich (gut)const newNumbers = [...numbers, 4];
console.log(numbers); // [1, 2, 3]console.log(newNumbers); // [1, 2, 3, 4]3. Funktionen höherer Ordnung: map, filter, reduce
Funktionen höherer Ordnung sind Funktionen, die andere Funktionen als Argumente entgegennehmen oder zurückgeben. Die drei bekanntesten Methoden in JavaScript sind map, filter und reduce. Sie ermöglichen die Verarbeitung von Arrays ohne Schleifen und Mutationen.
3.1. map() — Transformation eines Arrays
Die Methode map erstellt ein neues Array, indem sie eine Funktion auf jedes Element des ursprünglichen Arrays anwendet.
const prices = [100, 200, 300];const withTax = prices.map(price => price * 1.2);
console.log(withTax); // [120, 240, 360]// Das ursprüngliche Array wurde nicht verändertconsole.log(prices); // [100, 200, 300]3.2. filter() — Filterung eines Arrays
Die Methode filter gibt ein neues Array zurück, das nur die Elemente enthält, für die die übergebene Funktion true zurückgegeben hat.
const ages = [15, 22, 18, 30, 12];const adults = ages.filter(age => age >= 18);
console.log(adults); // [22, 18, 30]3.3. reduce() — Datenaggregation
Die Methode reduce reduziert ein Array auf einen einzigen Wert (Zahl, Objekt, Zeichenkette).
const numbers = [1, 2, 3, 4, 5];const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum); // 15Durch die Kombination dieser Methoden können komplexe Aufgaben im funktionalen Stil gelöst werden:
const users = [