Arrays sind geordnete Listen beliebiger Werte. Iterables sind das allgemeinere Konzept dahinter: Alles, was Symbol.iterator implementiert, also Arrays, Strings, Map und Set, kannst du mit for…of, Spread und Destrukturierung verarbeiten.
Arrays erzeugen
const nums = [1, 2, 3];
const gerade = Array.from({ length: 3 }, (_, i) => i * 2); // [0, 2, 4]
const chars = Array.from('abc'); // ['a', 'b', 'c']
const eins = Array.of(7); // [7]
Fallstrick: new Array(7) erzeugt kein Array mit der Zahl 7, sondern ein Array mit 7 leeren Plätzen.
Transformieren statt mutieren
map, filter und reduce geben neue Werte zurück und verändern das Original nicht. Seit ES2023 gibt es außerdem nicht-mutierende Varianten: toSorted, toReversed, toSpliced und with.
const users = [{ name: 'Ada', age: 36 }, { name: 'Linus', age: 28 }];
const namen = users.filter(({ age }) => age > 30).map(({ name }) => name);
const summe = users.reduce((acc, u) => acc + u.age, 0);
const sortiert = users.toSorted((a, b) => a.age - b.age);
sort() verändert das Original und vergleicht ohne Vergleichsfunktion als Strings: [10, 9, 1].sort() ergibt [1, 10, 9]. Gib deshalb immer eine Vergleichsfunktion mit.
Spread und Destrukturierung
const [first, , third, ...rest] = [1, 2, 3, 4, 5];
const kopie = [...nums, 4]; // flache Kopie
const unique = [...new Set([1, 1, 2, 3])]; // [1, 2, 3]
const letztes = nums.at(-1); // 3
Das Iterator-Protokoll
Ein Objekt ist iterierbar, wenn [Symbol.iterator]() einen Iterator zurückgibt. Dessen next() liefert jeweils { value, done }. Am einfachsten baust du so etwas mit Generatoren.
const range = (start, end) => ({
*[Symbol.iterator]() {
for (let i = start; i < end; i++) yield i;
},
});
for (const n of range(1, 4)) console.log(n); // 1, 2, 3
const arr = [...range(0, 3)]; // [0, 1, 2]
Tipp: for…in durchläuft Schlüssel, auch geerbte. Für die Werte eines Arrays nimmst du for…of. Für asynchrone Quellen wie Streams gibt es for await…of.