Aufgaben-Python/courses/javascript/03_funktionen_und_scope/README.md

173 lines
7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# JS 03: Funktionen, Gültigkeitsbereiche (Scope) & Closures 🔐
Willkommen zu **Modul 03** des JavaScript-Kurses!
In JavaScript sind Funktionen sogenannte **First-Class Citizens**: Sie können wie gewöhnliche Variablen gespeichert, als Argumente übergeben und von anderen Funktionen zurückgegeben werden (*Higher-Order Functions*).
In diesem Modul meisterst du moderne Funktionsarten, Gültigkeitsbereiche (*Scopes*) und eines der faszinierendsten Kernkonzepte von JavaScript: **Closures**!
---
## 💡 1. Das Wichtigste in Kürze
### A. Funktionsarten im Vergleich
#### 1. Function Declaration (Klassische Funktionsdeklaration)
Wird vollständig gehoistet (kann bereits vor ihrer Definition im Code aufgerufen werden):
```javascript
console.log(quadriere(4)); // 16 (funktioniert dank Hoisting!)
function quadriere(x) {
return x * x;
}
```
#### 2. Function Expression (Funktionsausdruck)
Wird einer Variablen zugewiesen und ist erst ab der Zuweisungszeile verfügbar:
```javascript
const verdopple = function(x) {
return x * 2;
};
```
#### 3. Arrow Function (Pfeilfunktion / ES6)
Kompakte Syntax, kein eigenes `this` oder `arguments`-Objekt:
```javascript
// Ausführliche Arrow Function:
const addiere = (a, b) => {
return a + b;
};
// Einzeilige Arrow Function mit implizitem Return:
const multipliziere = (a, b) => a * b;
```
---
### B. Moderne Parameter: Default- & Rest-Parameter
#### 1. Default-Parameter (Standardwerte)
Verhindert `undefined`, wenn kein Wert übergeben wird:
```javascript
function begruesse(name = "Gast", sprache = "de") {
return sprache === "de" ? `Hallo, ${name}!` : `Hello, ${name}!`;
}
console.log(begruesse()); // "Hallo, Gast!"
console.log(begruesse("Anna", "en")); // "Hello, Anna!"
```
#### 2. Rest-Parameter (`...rest`)
Sammelt eine beliebige Anzahl von Argumenten in einem echten JavaScript-Array:
```javascript
function maxZahl(...zahlen) {
// 'zahlen' ist ein echtes Array!
return Math.max(...zahlen);
}
console.log(maxZahl(3, 9, 21, 4)); // 21
```
---
### C. Gültigkeitsbereiche (Scopes) & Hoisting
JavaScript kennt drei Ebenen von Scopes:
```
┌─────────────────────────────────────────────────────────┐
│ 🌍 GLOBAL SCOPE (Überall im Programm sichtbar) │
│ const globalVar = "Welt"; │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 📦 FUNCTION SCOPE (Nur innerhalb der Funktion) │ │
│ │ function meineFunktion() { │ │
│ │ const funcVar = "Funktion"; │ │
│ │ │ │
│ │ ┌───────────────────────────────────────┐ │ │
│ │ │ 🔒 BLOCK SCOPE (if, for, { let/const})│ │ │
│ │ │ if (true) { │ │ │
│ │ │ const blockVar = "Block"; │ │ │
│ │ │ } │ │ │
│ │ └───────────────────────────────────────┘ │ │
│ │ } │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
```
- **`let` und `const`** besitzen **Block-Scope** (gelten nur innerhalb der `{ ... }` geschweiften Klammern).
- **`var`** besitzt nur **Function-Scope** (ignoriert `if`- und `for`-Blöcke) und sollte in modernem JS vermieden werden.
- **Lexical Scope (Statische Bindung):** Innere Funktionen können auf Variablen ihrer äußeren Eltern-Scopes zugreifen, aber nicht umgekehrt!
---
### D. Closures: Das Super-Feature
> **Definition Closure:** Eine Closure entsteht, wenn eine innere Funktion Zugriff auf Variablen ihres äußeren Gültigkeitsbereichs behält – **selbst nachdem die äußere Funktion ihre Ausführung längst beendet hat**.
```javascript
function erstelleSparschwein() {
let guthaben = 0; // Private Variable, von außen nicht direkt änderbar!
return function(einzahlung) {
guthaben += einzahlung;
return `Aktuelles Guthaben: ${guthaben} €`;
};
}
const meinKonto = erstelleSparschwein();
console.log(meinKonto(50)); // "Aktuelles Guthaben: 50 €"
console.log(meinKonto(100)); // "Aktuelles Guthaben: 150 €"
// Wichtig: 'guthaben' kann von außen nicht manipuliert werden (z.B. kein meinKonto.guthaben = 0)!
```
---
## 🔐 Die didaktische Analogie: "Der Tresor mit Geheimzahl"
Stelle dir eine Closure wie einen **verschlossenen Tresor mit einem Einwurf-Schlitz und Zahlenrad** vor:
- **Der Erbauer (Die äußere Factory-Funktion):**
Die äußere Funktion baut den Tresor und legt die interne Mechanik (die geschützten Variablen `let zaehler`) im Inneren des Gehäuses an.
- **Der Schlüsselanhänger (Die zurückgegebene innere Funktion):**
Du erhältst von der Funktion lediglich den Schlüssel (die Referenz auf die innere Funktion).
- **Geschützte Kapselung (Data Encapsulation):**
Niemand von außen kann die Tresorwand aufbrechen oder direkt an die internen Zahnräder fassen. Nur wenn du den Schlüssel drehst (`zaehler()`), verändert sich der interne Zählerstand kontrolliert.
- **Unabhängige Instanzen:**
Jeder neue Aufruf der äußeren Funktion baut einen komplett eigenständigen Tresor. Tresor A und Tresor B beeinflussen sich gegenseitig zu keinem Zeitpunkt!
---
## 🎯 Aufgaben & Teilziele in `aufgabe.js`
Öffne die Datei `aufgabe.js` und implementiere folgende 4 Funktionen:
1. **TODO 1: `erstelleZaehler(startWert = 0)`**
Gibt eine Zählerfunktion (Closure) zurück. Jeder Aufruf erhöht den internen Zähler um 1 und gibt den neuen Stand zurück.
2. **TODO 2: `multiplizierer(faktor)`**
Erzeugt eine Multiplikator-Funktion (Closure): `(x) => x * faktor`.
*Beispiel:* `const verdopple = multiplizierer(2); verdopple(5); // 10`
3. **TODO 3: `summiereAlles(...zahlen)`**
Nimmt beliebig viele Zahlen per Rest-Parameter entgegen und gibt deren Gesamtsumme zurück. Bei leerem Aufruf wird `0` zurückgegeben.
4. **TODO 4: `erstellePraefixierer(praefix)`**
Gibt eine Funktion (Closure) zurück, die vor jeden übergebenen String das vorgegebene `praefix` anhängt: `(text) => `${praefix}${text}``.
---
## 🧪 Tests ausführen
Öffne die Web-IDE oder führe die Testsuite aus:
```bash
# Im Browser:
workspace.html?course=javascript&track=track_1_grundlagen&chapter=03_funktionen_und_scope
```