Arrays im Detail verstehen
Arrays im Detail verstehen
Arrays sind eine der wichtigsten Datenstrukturen in JavaScript. In diesem Tutorial gehst du über die Grundlagen hinaus und lernst Arrays wirklich zu meistern.
Arrays erstellen
Verschiedene Wege
// 1. Array-Literal (empfohlen)
const zahlen = [1, 2, 3, 4, 5];
// 2. Array-Konstruktor
const leer = new Array(); // []
const mitLaenge = new Array(5); // [empty × 5] - Vorsicht!
const mitWerten = new Array(1, 2, 3); // [1, 2, 3]
// 3. Array.of() - Konsistenter als Konstruktor
const arr1 = Array.of(5); // [5] - nicht [empty × 5]!
const arr2 = Array.of(1, 2, 3); // [1, 2, 3]
// 4. Array.from() - Aus Iterable erstellen
const fromString = Array.from("Hallo"); // ["H", "a", "l", "l", "o"]
const fromSet = Array.from(new Set([1, 2, 3])); // [1, 2, 3]
// 5. Spread-Operator
const original = [1, 2, 3];
const kopie = [...original]; // [1, 2, 3] - neue Referenz!
Arrays mit Werten füllen
// Array mit gleichem Wert füllen
const fuenf_nullen = new Array(5).fill(0);
// [0, 0, 0, 0, 0]
// Array mit Index-Werten
const indizes = Array.from({ length: 5 }, (_, i) => i);
// [0, 1, 2, 3, 4]
// Array mit berechneten Werten
const quadrate = Array.from({ length: 5 }, (_, i) => i * i);
// [0, 1, 4, 9, 16]
// Zufallszahlen
const zufall = Array.from({ length: 10 }, () => Math.floor(Math.random() * 100));
// [42, 17, 83, ...] (zufällig)
Array-Eigenschaften
length
const arr = [1, 2, 3, 4, 5];
console.log(arr.length); // 5
// length ist schreibbar!
arr.length = 3;
console.log(arr); // [1, 2, 3] - abgeschnitten!
arr.length = 5;
console.log(arr); // [1, 2, 3, empty × 2] - mit Löchern!
// Array leeren
arr.length = 0;
console.log(arr); // []
Sparse Arrays (mit Löchern)
const sparse = [1, , , 4]; // Löcher!
console.log(sparse.length); // 4
console.log(sparse[1]); // undefined
console.log(1 in sparse); // false - Index existiert nicht!
// Unterschied zu undefined-Wert
const mitUndefined = [1, undefined, undefined, 4];
console.log(1 in mitUndefined); // true - Index existiert
Elemente zugreifen & ändern
Lesen
const arr = ["a", "b", "c", "d", "e"];
// Positiver Index
console.log(arr[0]); // "a"
console.log(arr[2]); // "c"
// Negativer Index - geht NICHT direkt!
console.log(arr[-1]); // undefined
// Letztes Element
console.log(arr[arr.length - 1]); // "e"
// Mit at() - moderne Methode mit negativem Index!
console.log(arr.at(0)); // "a"
console.log(arr.at(-1)); // "e" - Letztes!
console.log(arr.at(-2)); // "d" - Vorletztes!
Schreiben
const arr = [1, 2, 3];
// Element ändern
arr[0] = 10;
console.log(arr); // [10, 2, 3]
// Element am Ende hinzufügen
arr[arr.length] = 4;
console.log(arr); // [10, 2, 3, 4]
// Lücke erzeugen (vermeiden!)
arr[10] = 99;
console.log(arr); // [10, 2, 3, 4, empty × 6, 99]
console.log(arr.length); // 11
Elemente hinzufügen & entfernen
Am Ende (push/pop)
const stack = [];
// push - am Ende hinzufügen
stack.push("a"); // ["a"]
stack.push("b", "c"); // ["a", "b", "c"]
const laenge = stack.push("d");
console.log(laenge); // 4 - push gibt neue Länge zurück
// pop - vom Ende entfernen
const letztes = stack.pop();
console.log(letztes); // "d"
console.log(stack); // ["a", "b", "c"]
Am Anfang (unshift/shift)
const queue = [1, 2, 3];
// unshift - am Anfang hinzufügen
queue.unshift(0); // [0, 1, 2, 3]
queue.unshift(-2, -1); // [-2, -1, 0, 1, 2, 3]
// shift - vom Anfang entfernen
const erstes = queue.shift();
console.log(erstes); // -2
console.log(queue); // [-1, 0, 1, 2, 3]
Irgendwo (splice)
splice ist das Swiss Army Knife für Arrays:
const arr = ["a", "b", "c", "d", "e"];
// Entfernen: splice(startIndex, anzahlZuEntfernen)
const entfernt = arr.splice(2, 2);
console.log(entfernt); // ["c", "d"]
console.log(arr); // ["a", "b", "e"]
// Einfügen: splice(startIndex, 0, ...elemente)
arr.splice(2, 0, "x", "y");
console.log(arr); // ["a", "b", "x", "y", "e"]
// Ersetzen: splice(startIndex, anzahl, ...neueElemente)
arr.splice(1, 2, "NEU");
console.log(arr); // ["a", "NEU", "y", "e"]
Moderne Alternative: toSpliced()
toSpliced() verändert das Original nicht:
const original = [1, 2, 3, 4, 5];
const neues = original.toSpliced(2, 1, 99);
console.log(neues); // [1, 2, 99, 4, 5]
console.log(original); // [1, 2, 3, 4, 5] - unverändert!
Arrays kopieren
Shallow Copy (flache Kopie)
const original = [1, 2, [3, 4]];
// Spread-Operator
const kopie1 = [...original];
// slice()
const kopie2 = original.slice();
// Array.from()
const kopie3 = Array.from(original);
// Alle sind flache Kopien!
kopie1[0] = 99;
console.log(original[0]); // 1 - unverändert
kopie1[2][0] = 99; // Nested Array ändern
console.log(original[2][0]); // 99 - auch geändert! 😱
Deep Copy (tiefe Kopie)
const original = [1, 2, [3, 4]];
// Mit JSON (einfach, aber limitiert)
const tiefKopie = JSON.parse(JSON.stringify(original));
tiefKopie[2][0] = 99;
console.log(original[2][0]); // 3 - unverändert! ✅
// Mit structuredClone (modern)
const tiefKopie2 = structuredClone(original);
Arrays durchsuchen
indexOf / lastIndexOf
const arr = [1, 2, 3, 2, 1];
console.log(arr.indexOf(2)); // 1 - erste Position
console.log(arr.lastIndexOf(2)); // 3 - letzte Position
console.log(arr.indexOf(99)); // -1 - nicht gefunden
includes
const arr = [1, 2, 3, NaN];
console.log(arr.includes(2)); // true
console.log(arr.includes(99)); // false
console.log(arr.includes(NaN)); // true - funktioniert mit NaN!
console.log(arr.indexOf(NaN)); // -1 - indexOf findet NaN nicht!
find / findIndex
const users = [
{ id: 1, name: "Max" },
{ id: 2, name: "Lisa" },
{ id: 3, name: "Tom" }
];
// Objekt finden
const user = users.find(u => u.id === 2);
console.log(user); // { id: 2, name: "Lisa" }
// Index finden
const index = users.findIndex(u => u.id === 2);
console.log(index); // 1
// Nicht gefunden
const notFound = users.find(u => u.id === 99);
console.log(notFound); // undefined
findLast / findLastIndex (neu!)
const zahlen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Letztes Element das Bedingung erfüllt
const letzteGerade = zahlen.findLast(n => n % 2 === 0);
console.log(letzteGerade); // 10
const index = zahlen.findLastIndex(n => n % 2 === 0);
console.log(index); // 9
Arrays prüfen
Array.isArray()
console.log(Array.isArray([1, 2, 3])); // true
console.log(Array.isArray("abc")); // false
console.log(Array.isArray({ length: 3 })); // false
every / some
const zahlen = [2, 4, 6, 8, 10];
// every - ALLE müssen true sein
const alleGerade = zahlen.every(n => n % 2 === 0);
console.log(alleGerade); // true
// some - MINDESTENS EINER muss true sein
const hatGroesserAlsFuenf = zahlen.some(n => n > 5);
console.log(hatGroesserAlsFuenf); // true
// Praktisches Beispiel
const users = [
{ name: "Max", active: true },
{ name: "Lisa", active: true },
{ name: "Tom", active: false }
];
const alleAktiv = users.every(u => u.active); // false
const einerAktiv = users.some(u => u.active); // true
Arrays sortieren
sort()
// Achtung: sort() verändert das Original!
const zahlen = [10, 2, 5, 1, 8];
// Standard-sort() sortiert als STRINGS!
zahlen.sort();
console.log(zahlen); // [1, 10, 2, 5, 8] - falsch!
// Numerisch sortieren
zahlen.sort((a, b) => a - b);
console.log(zahlen); // [1, 2, 5, 8, 10] - richtig!
// Absteigend
zahlen.sort((a, b) => b - a);
console.log(zahlen); // [10, 8, 5, 2, 1]
toSorted() - ohne Mutation
const original = [3, 1, 2];
const sortiert = original.toSorted((a, b) => a - b);
console.log(sortiert); // [1, 2, 3]
console.log(original); // [3, 1, 2] - unverändert!
Objekte sortieren
const personen = [
{ name: "Clara", alter: 25 },
{ name: "Anna", alter: 30 },
{ name: "Ben", alter: 20 }
];
// Nach Alter
personen.sort((a, b) => a.alter - b.alter);
// Nach Name
personen.sort((a, b) => a.name.localeCompare(b.name));
Arrays umdrehen
const arr = [1, 2, 3, 4, 5];
// reverse() verändert Original
arr.reverse();
console.log(arr); // [5, 4, 3, 2, 1]
// toReversed() ohne Mutation
const original = [1, 2, 3];
const reversed = original.toReversed();
console.log(reversed); // [3, 2, 1]
console.log(original); // [1, 2, 3]
Arrays verbinden & teilen
concat / Spread
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [5, 6];
// concat
const verbunden = arr1.concat(arr2, arr3);
console.log(verbunden); // [1, 2, 3, 4, 5, 6]
// Spread (moderner)
const verbunden2 = [...arr1, ...arr2, ...arr3];
console.log(verbunden2); // [1, 2, 3, 4, 5, 6]
slice
const arr = [0, 1, 2, 3, 4, 5];
console.log(arr.slice(2)); // [2, 3, 4, 5] - ab Index 2
console.log(arr.slice(2, 4)); // [2, 3] - Index 2 bis 4 (exklusiv)
console.log(arr.slice(-2)); // [4, 5] - letzte 2
console.log(arr.slice(1, -1)); // [1, 2, 3, 4] - ohne erstes und letztes
flat / flatMap
// Verschachtelte Arrays "platt" machen
const nested = [1, [2, 3], [4, [5, 6]]];
console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]] - 1 Level
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6] - 2 Level
console.log(nested.flat(Infinity)); // Komplett flach
// flatMap = map + flat(1)
const sentences = ["Hallo Welt", "Wie geht es"];
const words = sentences.flatMap(s => s.split(" "));
console.log(words); // ["Hallo", "Welt", "Wie", "geht", "es"]
Arrays zu Strings
const arr = ["Apfel", "Banane", "Orange"];
// join
console.log(arr.join()); // "Apfel,Banane,Orange"
console.log(arr.join(" - ")); // "Apfel - Banane - Orange"
console.log(arr.join("")); // "ApfelBananeOrange"
// toString
console.log(arr.toString()); // "Apfel,Banane,Orange"
Performance-Tipps
// 1. push ist schneller als unshift
arr.push(x); // O(1) - schnell
arr.unshift(x); // O(n) - muss alles verschieben
// 2. Länge cachen bei großen Arrays
const len = arr.length;
for (let i = 0; i < len; i++) { }
// 3. Vorbefüllen statt dynamisch wachsen
const arr = new Array(1000); // Schneller
const arr = []; // Dann 1000x push - langsamer
// 4. splice vermeiden wenn möglich
// Alternativen: filter, slice, etc.
Zusammenfassung
| Methode | Mutiert? | Beschreibung |
|---|---|---|
push/pop | ✅ | Ende hinzufügen/entfernen |
unshift/shift | ✅ | Anfang hinzufügen/entfernen |
splice | ✅ | Überall ändern |
toSpliced | ❌ | splice ohne Mutation |
sort/reverse | ✅ | Sortieren/Umdrehen |
toSorted/toReversed | ❌ | Ohne Mutation |
slice | ❌ | Teil-Array kopieren |
concat/spread | ❌ | Arrays verbinden |
Übung: Erstelle eine Funktion groupBy(array, key), die ein Array von Objekten nach einem Schlüssel gruppiert. z.B. groupBy(users, "role") → { admin: [...], user: [...] }