# Funktionen und Datenstrukturen

Funktionen helfen dir, Code zu ordnen und wiederzuverwenden. Du lernst, eigene Funktionen zu schreiben, Werte zu übergeben und Ergebnisse zurückzugeben. Zusätzlich arbeitest du mit Arrays und Objekten, um mehrere zusammengehörige Informationen übersichtlich zu speichern und auszuwerten.

# Funktionen definieren und aufrufen

## Warum Funktionen wichtig sind

In Programmen tauchen oft Aufgaben auf, die mehrmals benötigt werden: einen Nutzer begrüßen, einen Preis berechnen oder eine Meldung ausgeben. Statt denselben Code immer wieder zu schreiben, kannst du ihn in einer **Funktion** bündeln.

Eine Funktion ist ein benannter Codeblock, der erst ausgeführt wird, wenn du ihn aufrufst.

```js
function begruessen() {
  console.log("Hallo! Schön, dass du da bist.");
}
```

Der Code innerhalb der geschweiften Klammern wird noch nicht automatisch ausgeführt. Zuerst wurde die Funktion nur **definiert**.

Um sie auszuführen, rufst du sie mit ihrem Namen und runden Klammern auf:

```js
begruessen();
```

Ausgabe in der Konsole:

```text
Hallo! Schön, dass du da bist.
```

> **Merke:** Eine Funktion definieren bedeutet, ihre Anleitung zu schreiben. Eine Funktion aufrufen bedeutet, diese Anleitung auszuführen.

---

## Eine Funktion definieren

Eine Funktionsdefinition besteht aus mehreren Teilen:

```js
function zeigeNachricht() {
  console.log("JavaScript macht Webseiten lebendig.");
}
```

| Teil | Bedeutung |
|---|---|
| `function` | Das Schlüsselwort zeigt: Hier beginnt eine Funktion. |
| `zeigeNachricht` | Der Name der Funktion. Du wählst ihn selbst. |
| `()` | Hier können später Werte für die Funktion stehen. |
| `{ ... }` | In diesen geschweiften Klammern steht der auszuführende Code. |

Ein Funktionsname sollte möglichst deutlich machen, **was die Funktion tut**. Gute Namen beginnen häufig mit einem Verb:

```js
function starteSpiel() {
  console.log("Das Spiel beginnt.");
}

function berechneSumme() {
  console.log(5 + 8);
}

function aendereFarbe() {
  console.log("Farbe wurde geändert.");
}
```

Weniger verständlich wäre dagegen ein Name wie `test()` oder `sache()`. Zwar funktioniert der Code, aber andere Personen — und auch dein zukünftiges Ich — verstehen dann schwerer, wofür die Funktion gedacht ist.

---

## Funktionen aufrufen

Damit JavaScript den Code in einer Funktion ausführt, musst du sie aufrufen:

```js
function zeigeUhrzeit() {
  console.log("Es ist Zeit für eine Pause.");
}

zeigeUhrzeit();
```

Wichtig sind die Klammern beim Aufruf:

```js
zeigeUhrzeit();
```

Ohne Klammern schreibst du nur den Namen der Funktion hin:

```js
zeigeUhrzeit;
```

Damit wird die Funktion **nicht ausgeführt**. Für Anfänger gilt daher als einfache Regel:

> Wenn eine Funktion jetzt etwas tun soll, schreibe ihren Namen mit `()`.

Du darfst eine Funktion auch mehrfach aufrufen:

```js
function klatschen() {
  console.log("👏 Klatsch!");
}

klatschen();
klatschen();
klatschen();
```

Die Konsole zeigt dann dreimal:

```text
👏 Klatsch!
👏 Klatsch!
👏 Klatsch!
```

---

## Code wiederverwenden

Der größte Vorteil von Funktionen ist die Wiederverwendung. Ohne Funktion müsstest du denselben Code kopieren:

```js
console.log("Willkommen im Lernprogramm!");
console.log("Viel Erfolg beim Üben!");

console.log("Willkommen im Lernprogramm!");
console.log("Viel Erfolg beim Üben!");
```

Mit einer Funktion ist der Code ordentlicher:

```js
function zeigeWillkommen() {
  console.log("Willkommen im Lernprogramm!");
  console.log("Viel Erfolg beim Üben!");
}

zeigeWillkommen();
zeigeWillkommen();
```

Falls du später den Begrüßungstext ändern möchtest, musst du ihn nur **an einer Stelle** anpassen:

```js
function zeigeWillkommen() {
  console.log("Willkommen beim JavaScript-Kurs!");
  console.log("Lerne Schritt für Schritt.");
}
```

Alle Aufrufe von `zeigeWillkommen()` verwenden automatisch die neue Version.

---

## Funktionen können mehrere Anweisungen enthalten

In einer Funktion darf mehr als eine Zeile stehen. JavaScript führt die Anweisungen von oben nach unten aus.

```js
function starteProgramm() {
  console.log("Programm wird gestartet.");
  console.log("Daten werden geladen.");
  console.log("Programm ist bereit.");
}

starteProgramm();
```

Ausgabe:

```text
Programm wird gestartet.
Daten werden geladen.
Programm ist bereit.
```

Du kannst in Funktionen auch Variablen verwenden:

```js
function zeigePunktestand() {
  const punkte = 120;
  console.log("Dein Punktestand: " + punkte);
}

zeigePunktestand();
```

---

## Funktionen und andere Funktionen

Eine Funktion kann auch eine andere Funktion aufrufen. Das hilft dabei, größere Aufgaben in kleine, gut verständliche Schritte aufzuteilen.

```js
function begruessen() {
  console.log("Hallo!");
}

function erklaereAufgabe() {
  console.log("Heute üben wir Funktionen.");
}

function starteLektion() {
  begruessen();
  erklaereAufgabe();
  console.log("Los geht's!");
}

starteLektion();
```

Beim Aufruf von `starteLektion()` passiert Folgendes:

1. `begruessen()` wird ausgeführt.
2. `erklaereAufgabe()` wird ausgeführt.
3. Die letzte Nachricht wird ausgegeben.

So kannst du Programme übersichtlich strukturieren.

---

## Die Reihenfolge von Definition und Aufruf

Bei normalen Funktionsdefinitionen kannst du eine Funktion in JavaScript oft schon vor ihrer Definition aufrufen:

```js
sageHallo();

function sageHallo() {
  console.log("Hallo!");
}
```

Der Code funktioniert. Für gut lesbaren Anfänger-Code ist es trotzdem meist übersichtlicher, zuerst die Funktion zu definieren und sie danach aufzurufen:

```js
function sageHallo() {
  console.log("Hallo!");
}

sageHallo();
```

Dadurch erkennt man beim Lesen sofort, was die Funktion macht, bevor sie verwendet wird.

---

## Häufige Fehler

### Klammern beim Aufruf vergessen

```js
function spielen() {
  console.log("Das Spiel läuft.");
}

spielen;
```

Hier erscheint keine Ausgabe, weil `spielen` nicht aufgerufen wurde.

**Richtig:**

```js
spielen();
```

### Den Funktionsnamen unterschiedlich schreiben

JavaScript unterscheidet Groß- und Kleinschreibung. `zeigeText` und `ZeigeText` sind zwei unterschiedliche Namen.

```js
function zeigeText() {
  console.log("Ein Text");
}

ZeigeText();
```

Das führt zu einem Fehler, weil `ZeigeText` nicht definiert wurde.

**Richtig:**

```js
zeigeText();
```

### Geschweifte Klammern vergessen

Der Funktionskörper braucht öffnende und schließende geschweifte Klammern:

```js
function testeFunktion() {
  console.log("Test");
}
```

Nicht so:

```js
function testeFunktion()
  console.log("Test");
```

### Semikolon nach dem Funktionsnamen

Nach der Definition einer klassischen Funktion setzt du kein Semikolon direkt hinter die schließende Klammer des Namens:

```js
function zeigeInfo() {
  console.log("Information");
}
```

Ein Semikolon nach `console.log(...)` ist dagegen üblich:

```js
console.log("Information");
```

---

## Beispiel: Ein einfaches Mini-Programm

Dieses Beispiel bündelt verschiedene Aufgaben in Funktionen:

```js
function zeigeTitel() {
  console.log("=== Zahlenraten ===");
}

function erklaereRegeln() {
  console.log("Rate eine Zahl zwischen 1 und 10.");
}

function verabschiedeDich() {
  console.log("Danke fürs Spielen!");
}

zeigeTitel();
erklaereRegeln();
verabschiedeDich();
```

Die Funktionen machen das Programm klar gegliedert:

- `zeigeTitel()` kümmert sich um die Überschrift.
- `erklaereRegeln()` zeigt die Spielregel.
- `verabschiedeDich()` beendet das Programm freundlich.

Später könntest du jede Funktion verändern oder erweitern, ohne den restlichen Code stark umzubauen.

---

## Übung: Eigene Funktionen schreiben

Schreibe drei Funktionen:

1. `zeigeName()` gibt deinen Namen in der Konsole aus.
2. `zeigeLieblingsfarbe()` gibt deine Lieblingsfarbe aus.
3. `starteVorstellung()` ruft die beiden anderen Funktionen auf und begrüßt die Person.

Rufe am Ende `starteVorstellung()` auf.

Eine mögliche Lösung:

```js
function zeigeName() {
  console.log("Mein Name ist Alex.");
}

function zeigeLieblingsfarbe() {
  console.log("Meine Lieblingsfarbe ist Blau.");
}

function starteVorstellung() {
  console.log("Hallo, ich stelle mich vor:");
  zeigeName();
  zeigeLieblingsfarbe();
}

starteVorstellung();
```

---

## Zusammenfassung

- Eine **Funktion** ist ein benannter Codeblock für eine bestimmte Aufgabe.
- Mit `function` definierst du eine Funktion.
- Mit `funktionsName()` rufst du sie auf.
- Funktionen helfen dir, wiederholten Code zu vermeiden und Programme besser zu ordnen.
- Aussagekräftige Namen wie `zeigeMenue()` oder `starteSpiel()` machen Code leichter verständlich.
- Eine Funktion kann mehrere Anweisungen und auch Aufrufe anderer Funktionen enthalten.

Im nächsten Schritt lernst du, wie Funktionen **Parameter** entgegennehmen und mit `return` Ergebnisse zurückgeben können.

# Parameter und Rückgabewerte

## Werte an Funktionen übergeben

Bisher können Funktionen feste Aufgaben ausführen. Häufig sollen sie aber mit *unterschiedlichen Daten* arbeiten. Dafür gibt es **Parameter**.

Ein Parameter ist ein Platzhalter in der Funktionsdefinition. Beim Aufruf erhält dieser Platzhalter einen konkreten Wert. Dieser konkrete Wert heißt **Argument**.

```js
function begrüße(name) {
  console.log("Hallo, " + name + "!");
}

begrüße("Mira");
begrüße("Jonas");
```

Die Ausgabe lautet:

```text
Hallo, Mira!
Hallo, Jonas!
```

`name` ist der Parameter. `"Mira"` und `"Jonas"` sind die Werte, die beim jeweiligen Funktionsaufruf übergeben werden.

---

## Parameter machen Funktionen wiederverwendbar

Ohne Parameter müsste für jede Begrüßung eine eigene Funktion geschrieben werden:

```js
function begrüßeMira() {
  console.log("Hallo, Mira!");
}

function begrüßeJonas() {
  console.log("Hallo, Jonas!");
}
```

Das funktioniert, ist aber unpraktisch. Mit einem Parameter reicht eine einzige Funktion:

```js
function begrüße(name) {
  console.log("Hallo, " + name + "!");
}
```

Diese Funktion kann nun für beliebig viele Namen verwendet werden.

```js
begrüße("Aylin");
begrüße("Ben");
begrüße("Chris");
```

---

## Mehrere Parameter verwenden

Eine Funktion kann auch mehrere Parameter haben. Sie werden durch Kommas getrennt.

```js
function addiere(zahl1, zahl2) {
  console.log(zahl1 + zahl2);
}

addiere(4, 7);
```

Die Ausgabe ist:

```text
11
```

JavaScript ordnet die Argumente der Reihenfolge nach zu:

```js
addiere(4, 7);
```

- `zahl1` erhält den Wert `4`.
- `zahl2` erhält den Wert `7`.

Ein weiteres Beispiel berechnet den Preis mehrerer gleicher Artikel:

```js
function berechneGesamtpreis(preis, anzahl) {
  console.log(preis * anzahl);
}

berechneGesamtpreis(3.5, 4);
```

Die Funktion gibt in der Konsole `14` aus.

> **Wichtig:** Die Namen der Parameter kannst du frei wählen. Sie sollten aber klar beschreiben, welche Werte erwartet werden.

Gut lesbar:

```js
function berechneGesamtpreis(preis, anzahl) {
  console.log(preis * anzahl);
}
```

Weniger verständlich:

```js
function berechneGesamtpreis(a, b) {
  console.log(a * b);
}
```

---

## Parameter sind lokale Variablen

Innerhalb einer Funktion verhalten sich Parameter wie Variablen. Du kannst mit ihnen rechnen, sie vergleichen oder in Texten verwenden.

```js
function prüfeAlter(alter) {
  if (alter >= 18) {
    console.log("Du bist volljährig.");
  } else {
    console.log("Du bist noch nicht volljährig.");
  }
}

prüfeAlter(20);
prüfeAlter(15);
```

Die Ausgabe:

```text
Du bist volljährig.
Du bist noch nicht volljährig.
```

Der Parameter `alter` existiert nur innerhalb der Funktion `prüfeAlter`.

```js
function zeigeZahl(zahl) {
  console.log(zahl);
}

zeigeZahl(8);

console.log(zahl);
```

Die letzte Zeile führt zu einem Fehler, weil `zahl` außerhalb der Funktion nicht bekannt ist.

---

## Standardwerte für Parameter

Manchmal wird beim Aufruf kein Wert übergeben. Dann kann ein **Standardwert** hilfreich sein.

```js
function begrüße(name = "Gast") {
  console.log("Hallo, " + name + "!");
}

begrüße("Lea");
begrüße();
```

Die Ausgabe lautet:

```text
Hallo, Lea!
Hallo, Gast!
```

Wird kein Argument angegeben, verwendet JavaScript den Standardwert `"Gast"`.

Auch mehrere Parameter können Standardwerte besitzen:

```js
function zeigeNachricht(text = "Keine Nachricht", dauer = 3) {
  console.log(text + " – Anzeige für " + dauer + " Sekunden");
}

zeigeNachricht("Gespeichert", 5);
zeigeNachricht();
```

---

## Werte mit `return` zurückgeben

Eine Funktion kann nicht nur etwas in der Konsole ausgeben. Sie kann auch ein Ergebnis an die Stelle zurückgeben, an der sie aufgerufen wurde. Dafür verwendest du `return`.

```js
function addiere(zahl1, zahl2) {
  return zahl1 + zahl2;
}

let ergebnis = addiere(4, 7);

console.log(ergebnis);
```

Die Ausgabe ist:

```text
11
```

Hier passiert Folgendes:

1. Die Funktion `addiere(4, 7)` wird aufgerufen.
2. Sie berechnet `4 + 7`.
3. `return` gibt das Ergebnis `11` zurück.
4. Das Ergebnis wird in der Variablen `ergebnis` gespeichert.
5. `console.log(ergebnis)` gibt den gespeicherten Wert aus.

Du kannst die Funktion auch direkt in `console.log()` verwenden:

```js
console.log(addiere(10, 5));
```

Oder ihr Ergebnis für weitere Berechnungen nutzen:

```js
let summe = addiere(8, 2);
let verdoppelteSumme = summe * 2;

console.log(verdoppelteSumme);
```

Die Ausgabe lautet:

```text
20
```

---

## Der Unterschied zwischen `console.log()` und `return`

Diese beiden Anweisungen werden leicht verwechselt, haben aber unterschiedliche Aufgaben.

```js
function zeigeSumme(zahl1, zahl2) {
  console.log(zahl1 + zahl2);
}
```

Diese Funktion zeigt das Ergebnis nur in der Konsole an. Das Ergebnis kann danach nicht weiterverwendet werden.

```js
let ergebnis = zeigeSumme(2, 3);

console.log(ergebnis);
```

Die Konsole zeigt:

```text
5
undefined
```

Warum erscheint `undefined`? Die Funktion hat keinen Wert zurückgegeben. Ohne `return` endet eine Funktion automatisch mit dem Rückgabewert `undefined`.

Mit `return` funktioniert es:

```js
function berechneSumme(zahl1, zahl2) {
  return zahl1 + zahl2;
}

let ergebnis = berechneSumme(2, 3);

console.log(ergebnis);
```

Die Ausgabe:

```text
5
```

**Merke:**

- `console.log()` zeigt einen Wert zur Kontrolle in der Konsole.
- `return` gibt einen Wert aus einer Funktion zurück.
- Einen Rückgabewert kannst du speichern, weiterrechnen oder an eine andere Funktion übergeben.

---

## `return` beendet die Funktion

Sobald JavaScript auf `return` trifft, wird die Funktion sofort beendet. Code darunter wird nicht mehr ausgeführt.

```js
function prüfeZahl(zahl) {
  if (zahl < 0) {
    return "Die Zahl ist negativ.";
  }

  console.log("Diese Ausgabe erfolgt nur bei null oder positiven Zahlen.");
  return "Die Zahl ist null oder positiv.";
}

console.log(prüfeZahl(-3));
console.log(prüfeZahl(5));
```

Für `-3` wird die `console.log()`-Zeile innerhalb der Funktion übersprungen. Die Funktion endet direkt bei `return`.

Dieses Verhalten ist besonders nützlich, um Fälle früh zu behandeln:

```js
function teile(dividend, divisor) {
  if (divisor === 0) {
    return "Division durch null ist nicht möglich.";
  }

  return dividend / divisor;
}

console.log(teile(12, 3));
console.log(teile(12, 0));
```

Die Ausgabe:

```text
4
Division durch null ist nicht möglich.
```

---

## Rückgabewerte mit Bedingungen

Funktionen können abhängig von einer Bedingung unterschiedliche Werte zurückgeben.

```js
function istVolljährig(alter) {
  if (alter >= 18) {
    return true;
  } else {
    return false;
  }
}

console.log(istVolljährig(21));
console.log(istVolljährig(16));
```

Die Ausgabe:

```text
true
false
```

Da der Vergleich `alter >= 18` selbst bereits `true` oder `false` liefert, kann die Funktion noch kürzer geschrieben werden:

```js
function istVolljährig(alter) {
  return alter >= 18;
}
```

Du kannst diese Funktion direkt in einer Bedingung einsetzen:

```js
if (istVolljährig(19)) {
  console.log("Zugang erlaubt.");
} else {
  console.log("Zugang nicht erlaubt.");
}
```

---

## Ein praktisches Beispiel: Rabatt berechnen

Die folgende Funktion berechnet einen neuen Preis nach einem prozentualen Rabatt.

```js
function berechneRabattPreis(preis, rabattProzent) {
  let rabatt = preis * rabattProzent / 100;
  return preis - rabatt;
}

let neuerPreis = berechneRabattPreis(80, 25);

console.log(neuerPreis);
```

Die Ausgabe lautet:

```text
60
```

Die Funktion erhält zwei Werte:

- `preis`: der ursprüngliche Preis
- `rabattProzent`: der Rabatt in Prozent

Sie berechnet zunächst den Rabatt und gibt anschließend den verminderten Preis zurück.

---

## Häufige Fehler

### Argumente in der falschen Reihenfolge übergeben

Bei mehreren Parametern ist die Reihenfolge wichtig.

```js
function stelleVor(name, alter) {
  console.log(name + " ist " + alter + " Jahre alt.");
}

stelleVor("Mara", 14);
```

Das ergibt:

```text
Mara ist 14 Jahre alt.
```

Wenn du die Werte vertauschst, entsteht ein unpassender Satz:

```js
stelleVor(14, "Mara");
```

Ausgabe:

```text
14 ist Mara Jahre alt.
```

---

### `return` mit `console.log()` verwechseln

```js
function quadriere(zahl) {
  console.log(zahl * zahl);
}
```

Diese Funktion gibt zwar etwas aus, liefert aber kein Ergebnis zurück. Wenn du später mit dem Ergebnis rechnen möchtest, brauchst du `return`:

```js
function quadriere(zahl) {
  return zahl * zahl;
}

let fläche = quadriere(6);

console.log(fläche);
```

---

### Code nach `return` erwarten

```js
function teste() {
  return "Fertig";
  console.log("Diese Zeile wird nie ausgeführt.");
}
```

Alles nach `return` innerhalb desselben Funktionsblocks ist nicht erreichbar.

---

## Übung: Temperatur umrechnen

Schreibe eine Funktion `celsiusZuFahrenheit`, die eine Temperatur in Celsius erhält und die passende Temperatur in Fahrenheit zurückgibt.

Zur Umrechnung gilt:

$$
\text{Fahrenheit} = \text{Celsius} \cdot 1{,}8 + 32
$$

Ein möglicher Aufruf soll so aussehen:

```js
let temperatur = celsiusZuFahrenheit(20);

console.log(temperatur);
```

Die Ausgabe soll sein:

```text
68
```

<details>
<summary>Lösung anzeigen</summary>

```js
function celsiusZuFahrenheit(celsius) {
  return celsius * 1.8 + 32;
}

let temperatur = celsiusZuFahrenheit(20);

console.log(temperatur);
```

</details>

---

## Übung: Größere Zahl finden

Schreibe eine Funktion `größereZahl`, die zwei Zahlen entgegennimmt und die größere Zahl zurückgibt.

Beispiel:

```js
console.log(größereZahl(12, 7));
```

Erwartete Ausgabe:

```text
12
```

Eine mögliche Lösung:

```js
function größereZahl(zahl1, zahl2) {
  if (zahl1 > zahl2) {
    return zahl1;
  } else {
    return zahl2;
  }
}

console.log(größereZahl(12, 7));
```

Was passiert, wenn beide Zahlen gleich sind? Passe die Funktion so an, dass sie in diesem Fall beispielsweise den Text `"Beide Zahlen sind gleich."` zurückgibt.

---

## Zusammenfassung

- **Parameter** sind Platzhalter für Werte, die eine Funktion beim Aufruf erhält.
- Eine Funktion kann einen oder mehrere Parameter besitzen.
- Mit **Standardwerten** bleibt eine Funktion sinnvoll nutzbar, auch wenn ein Argument fehlt.
- `return` gibt ein Ergebnis aus einer Funktion zurück.
- Rückgabewerte können in Variablen gespeichert, weiterverarbeitet oder in Bedingungen verwendet werden.
- `console.log()` zeigt Werte nur in der Konsole an und ersetzt kein `return`.
- Nach einem `return` wird der restliche Code der Funktion nicht mehr ausgeführt.

Im nächsten Abschnitt nutzt du **Arrays**, um mehrere Werte gemeinsam in einer geordneten Liste zu speichern.

# Arrays erstellen und nutzen

## Was sind Arrays?

Ein **Array** ist eine geordnete Liste von Werten. Es eignet sich immer dann, wenn du mehrere zusammengehörige Informationen speichern möchtest.

Statt für jede Lieblingsfarbe eine eigene Variable anzulegen:

```js
const farbe1 = "Rot";
const farbe2 = "Blau";
const farbe3 = "Grün";
```

kannst du alle Farben in einem Array zusammenfassen:

```js
const farben = ["Rot", "Blau", "Grün"];
```

Ein Array speichert seine Werte zwischen eckigen Klammern `[]`. Die einzelnen Einträge werden durch Kommas getrennt.

```js
const tiere = ["Hund", "Katze", "Kaninchen"];
const punkte = [12, 8, 20, 15];
const antworten = [true, false, true];
```

In einem Array können unterschiedliche Datentypen stehen:

```js
const gemischteWerte = ["Hallo", 42, true];
```

Für übersichtlichen Code ist es aber meistens sinnvoll, ähnliche Werte gemeinsam zu speichern: also zum Beispiel nur Namen, nur Zahlen oder nur Wahrheitswerte.

---

## Einträge über ihren Index auswählen

Jeder Eintrag in einem Array besitzt eine feste Position. Diese Position heißt **Index**.

Wichtig: Der erste Eintrag hat immer den Index `0`, nicht `1`.

```js
const staedte = ["Berlin", "Hamburg", "Köln"];
```

| Index | Wert |
|---:|---|
| 0 | `"Berlin"` |
| 1 | `"Hamburg"` |
| 2 | `"Köln"` |

Du greifst mit eckigen Klammern auf einen bestimmten Eintrag zu:

```js
const staedte = ["Berlin", "Hamburg", "Köln"];

console.log(staedte[0]); // Berlin
console.log(staedte[1]); // Hamburg
console.log(staedte[2]); // Köln
```

Wenn du einen Index verwendest, der nicht existiert, erhältst du `undefined`.

```js
console.log(staedte[5]); // undefined
```

> 💡 **Merke:** Bei Arrays beginnt das Zählen bei `0`. Das ist anfangs ungewohnt, aber in JavaScript und vielen anderen Programmiersprachen üblich.

---

## Die Anzahl der Einträge ermitteln

Mit der Eigenschaft `.length` findest du heraus, wie viele Werte ein Array enthält.

```js
const einkaufsliste = ["Brot", "Milch", "Äpfel"];

console.log(einkaufsliste.length); // 3
```

`.length` ist keine Funktion. Deshalb stehen hier **keine runden Klammern** dahinter.

```js
const zahlen = [4, 8, 15, 16];

console.log(zahlen.length); // 4
```

Die Länge eines Arrays ist besonders praktisch, wenn du mit Schleifen arbeitest.

---

## Einträge verändern

Ein Array, das mit `const` erstellt wurde, darf verändert werden. Du kannst also einzelne Werte ersetzen.

```js
const tage = ["Montag", "Dienstag", "Mittwoch"];

tage[1] = "Dienstagabend";

console.log(tage);
```

Ausgabe:

```js
["Montag", "Dienstagabend", "Mittwoch"]
```

`const` bedeutet hier: Die Variable `tage` darf nicht auf ein komplett neues Array zeigen. Der Inhalt des vorhandenen Arrays kann jedoch geändert werden.

```js
const tage = ["Montag", "Dienstag"];

// Das ist erlaubt:
tage[0] = "Sonntag";

// Das führt zu einem Fehler:
tage = ["Mittwoch", "Donnerstag"];
```

Wenn du das Array später vollständig ersetzen möchtest, verwendest du `let`.

```js
let aufgaben = ["Lernen", "Aufräumen"];

aufgaben = ["Einkaufen", "Kochen"];

console.log(aufgaben);
```

---

## Werte am Ende hinzufügen: `push()`

Mit der Methode `.push()` fügst du einen oder mehrere Werte am **Ende** eines Arrays hinzu.

```js
const musikrichtungen = ["Rock", "Pop"];

musikrichtungen.push("Jazz");

console.log(musikrichtungen);
```

Ausgabe:

```js
["Rock", "Pop", "Jazz"]
```

Du kannst auch mehrere Werte gleichzeitig hinzufügen:

```js
const zahlen = [1, 2, 3];

zahlen.push(4, 5);

console.log(zahlen);
```

Ausgabe:

```js
[1, 2, 3, 4, 5]
```

`.push()` verändert das vorhandene Array direkt.

---

## Den letzten Wert entfernen: `pop()`

Mit `.pop()` entfernst du den letzten Eintrag eines Arrays.

```js
const warteschlange = ["Mia", "Noah", "Emma"];

warteschlange.pop();

console.log(warteschlange);
```

Ausgabe:

```js
["Mia", "Noah"]
```

Außerdem gibt `.pop()` den entfernten Wert zurück. Das ist nützlich, wenn du ihn noch weiterverwenden möchtest.

```js
const warteschlange = ["Mia", "Noah", "Emma"];

const entferntePerson = warteschlange.pop();

console.log(entferntePerson); // Emma
console.log(warteschlange);   // ["Mia", "Noah"]
```

---

## Werte am Anfang hinzufügen und entfernen

Manchmal soll ein Wert nicht am Ende, sondern am Anfang eines Arrays stehen.

### Mit `unshift()` vorne hinzufügen

```js
const plaetze = ["Mitte", "Hinten"];

plaetze.unshift("Vorne");

console.log(plaetze);
```

Ausgabe:

```js
["Vorne", "Mitte", "Hinten"]
```

### Mit `shift()` den ersten Wert entfernen

```js
const plaetze = ["Vorne", "Mitte", "Hinten"];

const ersterPlatz = plaetze.shift();

console.log(ersterPlatz); // Vorne
console.log(plaetze);     // ["Mitte", "Hinten"]
```

| Methode | Aufgabe |
|---|---|
| `.push()` | Wert am Ende hinzufügen |
| `.pop()` | Letzten Wert entfernen |
| `.unshift()` | Wert am Anfang hinzufügen |
| `.shift()` | Ersten Wert entfernen |

---

## Arrays mit einer `for`-Schleife durchlaufen

Arrays werden sehr häufig mit einer `for`-Schleife verarbeitet. So kannst du jeden Eintrag nacheinander ausgeben.

```js
const obst = ["Apfel", "Banane", "Birne"];

for (let index = 0; index < obst.length; index++) {
  console.log(obst[index]);
}
```

Ausgabe:

```js
Apfel
Banane
Birne
```

Schauen wir uns die Schleife genauer an:

```js
for (let index = 0; index < obst.length; index++) {
  console.log(obst[index]);
}
```

- `let index = 0`: Die Schleife beginnt beim ersten Index.
- `index < obst.length`: Sie läuft nur, solange ein Eintrag vorhanden ist.
- `index++`: Nach jedem Durchlauf wird der Index um `1` erhöht.
- `obst[index]`: Der aktuelle Wert wird aus dem Array gelesen.

Die Bedingung `index < obst.length` ist wichtig. Bei drei Werten sind die gültigen Indizes `0`, `1` und `2`. Der Wert `3` wäre bereits außerhalb des Arrays.

---

## Ein praktisches Beispiel: Punkteliste auswerten

Stell dir vor, du speicherst die Punkte einer Person in mehreren Runden.

```js
const punkte = [12, 8, 15, 10];
let gesamtPunkte = 0;

for (let index = 0; index < punkte.length; index++) {
  gesamtPunkte = gesamtPunkte + punkte[index];
}

console.log("Gesamtpunkte: " + gesamtPunkte);
```

Ausgabe:

```js
Gesamtpunkte: 45
```

Die Variable `gesamtPunkte` startet mit `0`. Dann wird in jedem Schleifendurchlauf der aktuelle Wert aus dem Array addiert.

Du kannst auch prüfen, ob ein bestimmter Punktwert erreicht wurde:

```js
const punkte = [12, 8, 15, 10];

for (let index = 0; index < punkte.length; index++) {
  if (punkte[index] >= 15) {
    console.log("Sehr gutes Ergebnis: " + punkte[index]);
  }
}
```

Ausgabe:

```js
Sehr gutes Ergebnis: 15
```

---

## Mehrdimensionale Arrays kurz kennengelernt

Ein Array kann selbst weitere Arrays enthalten. Das nennt man ein **mehrdimensionales Array**.

```js
const sitzplan = [
  ["Anna", "Ben"],
  ["Clara", "David"]
];
```

Der erste Wert enthält ein Array:

```js
console.log(sitzplan[0]);
```

Ausgabe:

```js
["Anna", "Ben"]
```

Um auf einen einzelnen Namen zuzugreifen, verwendest du zwei Indizes:

```js
console.log(sitzplan[0][1]); // Ben
console.log(sitzplan[1][0]); // Clara
```

Für den Einstieg reichen einfache Arrays meistens aus. Mehrdimensionale Arrays begegnen dir später zum Beispiel bei Spielbrettern, Tabellen oder Stundenplänen.

---

## Häufige Fehler

### Beim Index bei `1` beginnen

```js
const farben = ["Rot", "Blau", "Grün"];

console.log(farben[1]); // Blau
```

Wer den ersten Wert erwartet, wird überrascht sein: `farben[1]` ist bereits der zweite Eintrag. Der erste Eintrag ist `farben[0]`.

### `.length` mit Klammern schreiben

```js
const namen = ["Lea", "Tom"];

console.log(namen.length());
```

Das führt zu einem Fehler. Richtig ist:

```js
console.log(namen.length);
```

### Einen nicht vorhandenen Index verwenden

```js
const monate = ["Januar", "Februar"];

console.log(monate[2]); // undefined
```

Das Array hat nur die Indizes `0` und `1`.

### Bei Schleifen `<=` verwenden

```js
const namen = ["Lea", "Tom"];

for (let index = 0; index <= namen.length; index++) {
  console.log(namen[index]);
}
```

Diese Schleife gibt am Ende zusätzlich `undefined` aus. Verwende stattdessen `<`:

```js
for (let index = 0; index < namen.length; index++) {
  console.log(namen[index]);
}
```

---

## Übung: Eine einfache To-do-Liste

Erstelle ein Array mit drei Aufgaben. Gib zunächst alle Aufgaben aus. Füge dann eine weitere Aufgabe hinzu und entferne anschließend die erste Aufgabe.

**Aufgabe:**

1. Erstelle ein Array namens `aufgaben`.
2. Speichere mindestens drei Texte darin.
3. Füge mit `.push()` eine Aufgabe hinzu.
4. Entferne mit `.shift()` die erste Aufgabe.
5. Gib das fertige Array in der Konsole aus.

Eine mögliche Lösung:

```js
const aufgaben = ["Hausaufgaben machen", "Zimmer aufräumen", "Einkaufen"];

aufgaben.push("E-Mail schreiben");
aufgaben.shift();

console.log(aufgaben);
```

Ausgabe:

```js
["Zimmer aufräumen", "Einkaufen", "E-Mail schreiben"]
```

---

## Übung: Namen begrüßen

Erstelle ein Array mit mehreren Namen. Schreibe eine `for`-Schleife, die jede Person einzeln begrüßt.

Eine mögliche Lösung:

```js
const namen = ["Aylin", "Jonas", "Mara"];

for (let index = 0; index < namen.length; index++) {
  console.log("Hallo, " + namen[index] + "!");
}
```

Ausgabe:

```js
Hallo, Aylin!
Hallo, Jonas!
Hallo, Mara!
```

---

## Das Wichtigste auf einen Blick

- Arrays speichern mehrere Werte in einer geordneten Liste.
- Arrays werden mit eckigen Klammern erstellt: `["Wert 1", "Wert 2"]`.
- Der erste Eintrag hat den Index `0`.
- Mit `.length` erhältst du die Anzahl der Einträge.
- Mit `.push()` und `.pop()` bearbeitest du das Ende eines Arrays.
- Mit `.unshift()` und `.shift()` bearbeitest du den Anfang.
- Eine `for`-Schleife hilft dir, alle Werte eines Arrays nacheinander zu verarbeiten.

Im nächsten Abschnitt lernst du **Objekte** kennen. Während Arrays mehrere Werte in einer Reihenfolge speichern, helfen Objekte dabei, Informationen mit klaren Eigenschaften wie Name, Alter oder Farbe zu ordnen.

# Objekte für strukturierte Daten

## Was sind Objekte?

Ein **Objekt** fasst mehrere Informationen zusammen, die zu einer Sache gehören. Jede Information erhält dabei einen eindeutigen Namen.

Stell dir ein Benutzerprofil vor: Es hat einen Namen, ein Alter und vielleicht eine E-Mail-Adresse. Statt für jede Information eine eigene Variable anzulegen, kannst du sie gemeinsam in einem Objekt speichern.

```js
const person = {
  name: "Mira",
  alter: 24,
  email: "mira@example.de"
};
```

Das Objekt `person` beschreibt eine Person mit drei Eigenschaften.

- `name`, `alter` und `email` heißen **Eigenschaften** oder *Properties*.
- Die Werte rechts vom Doppelpunkt gehören jeweils zu einer Eigenschaft.
- Die Eigenschaften werden durch Kommata getrennt.
- Das gesamte Objekt steht zwischen geschweiften Klammern `{}`.

## Eigenschaften auslesen

Um auf eine Eigenschaft zuzugreifen, verwendest du meist die **Punktnotation**:

```js
const person = {
  name: "Mira",
  alter: 24,
  email: "mira@example.de"
};

console.log(person.name);
console.log(person.alter);
```

Die Konsole gibt aus:

```text
Mira
24
```

Du kannst Eigenschaften auch direkt in Texten verwenden:

```js
console.log("Hallo, " + person.name + "!");
```

Ausgabe:

```text
Hallo, Mira!
```

Mit einem Template-String wirkt derselbe Code oft übersichtlicher:

```js
console.log(`Hallo, ${person.name}! Du bist ${person.alter} Jahre alt.`);
```

## Eigenschaften verändern und ergänzen

Die Werte eines Objekts können verändert werden:

```js
const spieler = {
  name: "Noah",
  punkte: 10
};

spieler.punkte = 15;

console.log(spieler.punkte);
```

Ausgabe:

```text
15
```

Auch neue Eigenschaften lassen sich nachträglich hinzufügen:

```js
spieler.level = 2;

console.log(spieler);
```

Das Objekt enthält nun `name`, `punkte` und `level`.

> **Wichtig:** Ein Objekt kann mit `const` erstellt werden, obwohl seine Eigenschaften später noch geändert werden dürfen. `const` verhindert nur, dass die Variable selbst auf ein vollständig anderes Objekt zeigt.

Das ist erlaubt:

```js
const buch = {
  titel: "JavaScript leicht gemacht",
  seiten: 180
};

buch.seiten = 200;
```

Das wäre dagegen ein Fehler:

```js
const buch = {
  titel: "JavaScript leicht gemacht"
};

buch = {
  titel: "Ein anderes Buch"
};
```

## Eigenschaften mit eckigen Klammern auswählen

Neben der Punktnotation gibt es die **Klammernotation**:

```js
const wetter = {
  stadt: "Hamburg",
  temperatur: 18
};

console.log(wetter["stadt"]);
```

Das Ergebnis ist dasselbe wie bei `wetter.stadt`.

Die Klammernotation ist besonders nützlich, wenn der Name einer Eigenschaft in einer Variablen gespeichert ist:

```js
const profil = {
  name: "Lea",
  hobby: "Zeichnen"
};

const eigenschaft = "hobby";

console.log(profil[eigenschaft]);
```

Ausgabe:

```text
Zeichnen
```

Mit Punktnotation würde JavaScript nach einer Eigenschaft namens `eigenschaft` suchen:

```js
console.log(profil.eigenschaft);
```

Da diese Eigenschaft nicht existiert, erhältst du `undefined`.

## Fehlende Eigenschaften

Wenn du auf eine Eigenschaft zugreifst, die nicht vorhanden ist, entsteht normalerweise kein Fehler. JavaScript gibt stattdessen `undefined` zurück.

```js
const tier = {
  art: "Katze",
  name: "Luna"
};

console.log(tier.alter);
```

Ausgabe:

```text
undefined
```

Du kannst das in einer Bedingung prüfen:

```js
if (tier.alter === undefined) {
  console.log("Das Alter ist nicht bekannt.");
}
```

## Objekte und Arrays vergleichen

Ein **Array** speichert mehrere Werte in einer Reihenfolge. Du greifst über einen Zahlenindex darauf zu.

```js
const farben = ["Rot", "Grün", "Blau"];

console.log(farben[0]);
```

Ein **Objekt** speichert Werte unter aussagekräftigen Namen.

```js
const auto = {
  marke: "Volkswagen",
  modell: "ID.3",
  baujahr: 2023
};

console.log(auto.marke);
```

Verwende Arrays, wenn die **Reihenfolge** wichtig ist oder wenn du eine Liste gleichartiger Werte hast:

```js
const lieblingsObst = ["Apfel", "Banane", "Erdbeere"];
```

Verwende Objekte, wenn verschiedene Informationen eine Sache **beschreiben**:

```js
const lieblingsFilm = {
  titel: "Die Reise zum Mond",
  jahr: 2024,
  gesehen: true
};
```

## Objekte mit verschiedenen Datentypen

Die Werte eines Objekts können unterschiedliche Datentypen haben:

```js
const kurs = {
  titel: "JavaScript für Anfänger",
  lektionen: 20,
  aktiv: true,
  beschreibung: null
};
```

In diesem Objekt ist:

- `titel` ein String,
- `lektionen` eine Zahl,
- `aktiv` ein Boolean,
- `beschreibung` hat momentan den Wert `null`.

Auch Arrays und andere Objekte können als Werte gespeichert werden.

```js
const rezept = {
  name: "Obstsalat",
  portionen: 2,
  zutaten: ["Apfel", "Banane", "Trauben"]
};

console.log(rezept.zutaten[1]);
```

Ausgabe:

```text
Banane
```

Hier greifst du zuerst auf die Eigenschaft `zutaten` zu. Sie enthält ein Array. Anschließend wählst du mit `[1]` das zweite Element des Arrays aus.

## Verschachtelte Objekte

Ein Objekt kann wiederum ein anderes Objekt enthalten. Das nennt man ein **verschachteltes Objekt**.

```js
const benutzer = {
  name: "Sofia",
  kontakt: {
    email: "sofia@example.de",
    stadt: "Köln"
  }
};
```

Um die Stadt auszugeben, verbindest du die Zugriffe:

```js
console.log(benutzer.kontakt.stadt);
```

Ausgabe:

```text
Köln
```

Die Struktur lässt sich so lesen:

1. Nimm das Objekt `benutzer`.
2. Daraus nimm die Eigenschaft `kontakt`.
3. Daraus nimm die Eigenschaft `stadt`.

## Eine Liste von Objekten

Sehr häufig werden **Arrays und Objekte kombiniert**. Zum Beispiel kann ein Array mehrere Produkte enthalten. Jedes Produkt ist dabei ein eigenes Objekt.

```js
const produkte = [
  {
    name: "Notizbuch",
    preis: 4.99
  },
  {
    name: "Stift",
    preis: 1.5
  },
  {
    name: "Rucksack",
    preis: 39.99
  }
];
```

Du kannst nun ein bestimmtes Produkt auswählen:

```js
console.log(produkte[0].name);
console.log(produkte[2].preis);
```

Ausgabe:

```text
Notizbuch
39.99
```

Mit einer `for`-Schleife kannst du alle Produkte ausgeben:

```js
for (let i = 0; i < produkte.length; i++) {
  console.log(`${produkte[i].name}: ${produkte[i].preis} Euro`);
}
```

Ausgabe:

```text
Notizbuch: 4.99 Euro
Stift: 1.5 Euro
Rucksack: 39.99 Euro
```

## Methoden in Objekten

Ein Objekt kann nicht nur Daten speichern, sondern auch eine Funktion enthalten. Eine Funktion innerhalb eines Objekts heißt **Methode**.

```js
const hund = {
  name: "Bello",
  begruessen: function () {
    console.log("Wuff! Ich heiße " + this.name + ".");
  }
};

hund.begruessen();
```

Ausgabe:

```text
Wuff! Ich heiße Bello.
```

Das Wort `this` bedeutet hier: *dieses Objekt*. In der Methode steht `this.name` also für `hund.name`.

Für den Einstieg genügt es, sich zu merken:

- Eigenschaften speichern Daten.
- Methoden führen eine Aktion aus, die zu diesem Objekt gehört.

## Häufige Fehler

### Eigenschaftsnamen vergessen

Zwischen Eigenschaft und Wert muss ein Doppelpunkt stehen:

```js
const person = {
  name: "Mira",
  alter: 24
};
```

Das wäre falsch:

```js
const person = {
  name = "Mira"
};
```

### Komma zwischen Eigenschaften vergessen

```js
const person = {
  name: "Mira",
  alter: 24
};
```

Zwischen den Eigenschaften steht ein Komma. Nach der letzten Eigenschaft ist kein Komma erforderlich.

### Punktnotation bei einer Variablen verwenden

Wenn der Eigenschaftsname in einer Variablen steckt, brauchst du eckige Klammern:

```js
const konto = {
  inhaber: "Emil",
  kontostand: 250
};

const auswahl = "kontostand";

console.log(konto[auswahl]);
```

Nicht:

```js
console.log(konto.auswahl);
```

### Auf ein nicht vorhandenes Objekt zugreifen

Dieser Code führt zu einem Fehler, weil `adresse` nicht existiert:

```js
const person = {
  name: "Mira"
};

console.log(person.adresse.stadt);
```

Prüfe zunächst, ob die Eigenschaft vorhanden ist:

```js
if (person.adresse !== undefined) {
  console.log(person.adresse.stadt);
}
```

## Übung: Ein Filmobjekt erstellen

Erstelle ein Objekt namens `film`. Es soll diese Eigenschaften enthalten:

- `titel` mit einem Filmtitel
- `jahr` mit dem Erscheinungsjahr
- `genre` mit einem Genre
- `gesehen` mit dem Wert `true` oder `false`

Gib anschließend einen Satz in dieser Form aus:

```text
Der Film ... erschien im Jahr ....
```

Ändere danach den Wert von `gesehen` auf `true` und ergänze eine Eigenschaft `bewertung`.

### Mögliche Lösung

```js
const film = {
  titel: "Sternenreise",
  jahr: 2022,
  genre: "Science-Fiction",
  gesehen: false
};

console.log(`Der Film ${film.titel} erschien im Jahr ${film.jahr}.`);

film.gesehen = true;
film.bewertung = 8;

console.log(film);
```

## Das Wichtigste auf einen Blick

- Objekte speichern mehrere zusammengehörige Werte in einer Struktur.
- Eigenschaften bestehen aus einem Namen und einem Wert, etwa `name: "Mira"`.
- Mit `objekt.eigenschaft` liest oder änderst du Eigenschaften.
- Mit `objekt["eigenschaft"]` kannst du Eigenschaften dynamisch auswählen.
- Objekte können Zahlen, Texte, Booleans, Arrays, Funktionen und weitere Objekte enthalten.
- Arrays mit Objekten sind ideal für Listen wie Produkte, Benutzer oder Filme.