Mit der destruktiven Zuweisung für Arrays (Array-Destructuring, ES2015) lassen sich Werte aus einem Array per Position direkt in einzelne Variablen entpacken — ohne Index-Zugriff. Die Syntax const [a, b] = arr ersetzt das umständliche const a = arr[0]; const b = arr[1]. Dazu kommen Defaults für nicht vorhandene Werte, ein Rest-Pattern für den Rest der Elemente, Skip-Slots zum Überspringen einzelner Positionen und Verschachtelung für mehrdimensionale Arrays. Array-Destructuring ist die Grundlage für useState-artige Tupel-Returns, den klassischen Variablen-Swap ohne Hilfsvariable und vieles andere.

Grundform

Die Syntax: links eine Klammer-Liste von Bezeichnern, rechts ein Array (oder allgemein: eine Iterable).

JavaScript grundform.js
const farben = ['rot', 'grün', 'blau'];
const [erste, zweite, dritte] = farben;

console.log(erste);   // 'rot'
console.log(zweite);  // 'grün'
console.log(dritte);  // 'blau'

// Auch mit let — Reassignment erlaubt
let [a, b] = [1, 2];
[a, b] = [b, a];   // siehe Swap weiter unten
Output
rot
grün
blau

Die Zuweisung passiert positional — die Reihenfolge in den Klammern bestimmt, welches Array-Element wo landet.

Slots überspringen

Mit leeren Kommas lassen sich Positionen überspringen — praktisch, wenn man nur bestimmte Elemente braucht.

JavaScript skip.js
const items = ['a', 'b', 'c', 'd', 'e'];

// Nur erste und dritte
const [erste, , dritte] = items;
console.log(erste, dritte);    // 'a' 'c'

// Nur die fünfte
const [, , , , fuenfte] = items;
console.log(fuenfte);          // 'e'

// Mit Rest am Ende
const [, , ...restAbDrei] = items;
console.log(restAbDrei);       // ['c', 'd', 'e']
Output
a c
e
[ 'c', 'd', 'e' ]

Wer drei oder mehr Slots überspringt, schreibt oft besser eine explizite Index-Variable — Lesbarkeit gewinnt über Kompaktheit.

Default-Werte für fehlende Positionen

Wenn das Array kürzer ist als das Destructuring-Pattern, bekommen die überzähligen Variablen undefined — außer ein Default ist gesetzt.

JavaScript defaults.js
const kurz = ['a'];
const [x = 'X', y = 'Y', z = 'Z'] = kurz;
console.log(x, y, z);   // 'a' 'Y' 'Z'

// Default greift NUR bei undefined
const mitNull = [null, undefined];
const [a = 'A', b = 'B'] = mitNull;
console.log(a, b);      // null 'B' — null ist KEIN Trigger
Output
a Y Z
null B

Wichtig: nur undefined löst den Default aus. null, 0, '', false werden als Werte akzeptiert.

Rest-Pattern — der Schwanz als Array

Mit ...name an letzter Position lässt sich der Rest des Arrays in einer Variable sammeln. Das Resultat ist immer ein echtes Array — auch wenn das Original ein Iterable war.

JavaScript rest.js
const zahlen = [10, 20, 30, 40, 50];

const [erste, zweite, ...rest] = zahlen;
console.log(erste);   // 10
console.log(zweite);  // 20
console.log(rest);    // [30, 40, 50]

// Auch ein leeres Rest ist gültig
const [a, b, c, ...rest2] = [1, 2, 3];
console.log(rest2);   // [] — kein undefined, sondern leeres Array
Output
10
20
[ 30, 40, 50 ]
[]

Rest muss letzte Position sein — [a, ...rest, b] ist SyntaxError. Das ist eindeutig: Rest sammelt „den Rest", danach kann nichts mehr kommen.

Klassischer Swap ohne Hilfsvariable

Eine der elegantesten Anwendungen: zwei Variablen tauschen ohne temp-Variable.

JavaScript swap.js
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b);   // 2 1

// Drei-fach-Rotation
let x = 'A', y = 'B', z = 'C';
[x, y, z] = [z, x, y];
console.log(x, y, z); // 'C' 'A' 'B'
Output
2 1
C A B

Hinter den Kulissen erzeugt die Engine ein temporäres Array [b, a] und destructured es zurück — der Effekt ist temp-frei aus Programmierer-Sicht.

Verschachtelte Patterns

Destructuring lässt sich für mehrdimensionale Arrays beliebig tief schachteln.

JavaScript verschachtelt.js
const matrix = [[1, 2], [3, 4], [5, 6]];

const [[a, b], [c, d], [e, f]] = matrix;
console.log(a, b, c, d, e, f);   // 1 2 3 4 5 6

// Auch gemischt mit Skip und Defaults
const koordinaten = [[10, 20], [30]];
const [[x1, y1], [x2, y2 = 0]] = koordinaten;
console.log(x1, y1, x2, y2);     // 10 20 30 0
Output
1 2 3 4 5 6
10 20 30 0

Tief verschachtelte Patterns sind meist schwerer lesbar als ein Zwischenschritt — Faustregel: nicht mehr als zwei Ebenen.

In Funktions-Parametern

Destructuring funktioniert direkt am Parameter-Slot — sehr verbreitet bei Tupel-Returns und API-Argumenten.

JavaScript params.js
// Tupel-Argument
function distanz([x1, y1], [x2, y2]) {
    return Math.hypot(x2 - x1, y2 - y1);
}

console.log(distanz([0, 0], [3, 4]));   // 5

// Mit Default falls leer
function ersteBeide([a = 0, b = 0] = []) {
    return a + b;
}
console.log(ersteBeide([10, 20]));      // 30
console.log(ersteBeide());              // 0 — = [] default
Output
5
30
0

Das = [] am Ende ist wichtig: ohne Default würde ersteBeide() versuchen, undefined zu destrukturieren — TypeError.

Funktioniert auf beliebigen Iterables

Array-Destructuring nutzt das Iterator-Protokoll — es funktioniert auf jeder iterable Datenstruktur, nicht nur auf echten Arrays.

JavaScript iterables.js
// String — pro Codepoint
const [c1, c2, c3] = 'abc';
console.log(c1, c2, c3);   // 'a' 'b' 'c'

// Set
const [erstes, zweites] = new Set([10, 20, 30]);
console.log(erstes, zweites);

// Map — als [key, value]-Tupel
const map = new Map([['a', 1], ['b', 2]]);
const [[k1, v1], [k2, v2]] = map;
console.log(k1, v1, k2, v2);

// Generator
function* zaehlen() { yield 1; yield 2; yield 3; }
const [g1, g2] = zaehlen();
console.log(g1, g2);
Output
a b c
10 20
a 1 b 2
1 2

Das ist mehr als nur Array-Syntax — es ist das Iterable-Destructuring, das zufällig auf Arrays am häufigsten verwendet wird.

Tupel-Returns — das useState-Pattern

React's useState liefert ein Tupel [state, setter]. Array-Destructuring macht die Aufnahme idiomatisch:

JavaScript usestate-pattern.js
// Eigene Tupel-API
function useCounter(start = 0) {
    let wert = start;
    return [
        () => wert,
        (n) => { wert = n; },
        () => { wert++; },
    ];
}

const [lese, setze, inkrement] = useCounter(10);
console.log(lese());   // 10
setze(99);
console.log(lese());   // 99
inkrement();
console.log(lese());   // 100
Output
10
99
100

Im Gegensatz zu Object-Returns gibt der Aufrufer hier die Namen vor — [state, setState] kann genauso [count, setCount] heißen. Das macht Tupel-Returns flexibel für mehrere parallele Instanzen.

Interessantes

Destructuring ist Iterable-basiert, nicht Array-spezifisch

const [a, b] = irgendwas funktioniert, sobald irgendwas iterable ist — also Symbol.iterator implementiert. Arrays sind nur der häufigste Fall. Map, Set, String, Generator, NodeList, alle: gehen.

Default greift nur bei undefined, nicht null

const [x = 5] = [null] liefert x === null. Das ist konsistent mit Function-Parameter-Defaults. Wenn man auch null als „leer" werten will, hilft die ??-Coalescing-Form nach dem Destructuring: const x = x ?? 5.

Rest-Pattern liefert immer ein echtes Array

Auch wenn die Quelle ein Set oder ein Generator war, ist rest in [a, ...rest] immer ein echtes Array — kein Set, kein Iterator. Praktisch, weil man darauf direkt map/filter/reduce nutzen kann.

Swap funktioniert dank temporärem Array

[a, b] = [b, a] erzeugt zur Laufzeit ein 2-Element-Array [b-Wert, a-Wert], destructured es und weist zu. Die Engine optimiert das oft inline-weg — Performance ist also kein Argument gegen den Trick.

Destructuring auf undefined oder null wirft TypeError

const [a] = undefined wirft TypeError: undefined is not iterable. Daher gilt: bei optionalen Parametern = [] als Default setzen, um den Fehler zu vermeiden. function f([a, b] = []) ist defensiv.

Rest muss letzte Position sein — SyntaxError sonst

const [a, ...rest, b] = arr ist ein SyntaxError. Logisch: Rest sammelt „alles, was übrig ist", danach kann nichts mehr kommen. Auch in Object-Destructuring gilt dieselbe Regel.

Object-Destructuring + Array-Destructuring mischbar

const {name, koords: [x, y]} = obj kombiniert beide Formen. Erst wird per Object-Key zugegriffen, dann das Resultat per Array-Position destructured. Tiefe Pattern-Kombinationen sind möglich — sollten aber sparsam genutzt werden, weil sie schwer lesbar werden.

Performance: Destructuring ist genauso schnell wie Index-Zugriff

Moderne Engines inline-optimieren Destructuring auf Native-Index-Reads. Im Hot-Loop kein messbarer Unterschied zu const a = arr[0]; const b = arr[1]. Daher: stilistisch wählen, nicht performance-getrieben.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Arrays

Zur Übersicht