JavaScript Fortgeschritten

Destructuring in JavaScript

Destructuring in JavaScript

Destructuring ermöglicht es, Werte aus Arrays und Objekten elegant zu extrahieren. Es macht deinen Code kürzer und lesbarer.

Array Destructuring

Grundlagen

const fruechte = ["Apfel", "Banane", "Orange"];

// Ohne Destructuring
const erste = fruechte[0];
const zweite = fruechte[1];
const dritte = fruechte[2];

// Mit Destructuring
const [a, b, c] = fruechte;
console.log(a);  // "Apfel"
console.log(b);  // "Banane"
console.log(c);  // "Orange"

Elemente überspringen

const zahlen = [1, 2, 3, 4, 5];

// Nur erstes und drittes
const [erstes, , drittes] = zahlen;
console.log(erstes);   // 1
console.log(drittes);  // 3

// Nur das letzte... mit Rest-Operator
const [, , , , letztes] = zahlen;
console.log(letztes);  // 5

Rest-Operator (…)

const zahlen = [1, 2, 3, 4, 5];

const [erste, zweite, ...rest] = zahlen;
console.log(erste);   // 1
console.log(zweite);  // 2
console.log(rest);    // [3, 4, 5]

// Praktisch: Kopf und Schwanz
const [kopf, ...schwanz] = [1, 2, 3, 4];
console.log(kopf);     // 1
console.log(schwanz);  // [2, 3, 4]

Default-Werte

const arr = [1];

const [a, b = 10, c = 20] = arr;
console.log(a);  // 1
console.log(b);  // 10 (Default, weil undefined)
console.log(c);  // 20 (Default, weil undefined)

// Nur bei undefined, nicht bei null!
const [x = 5] = [null];
console.log(x);  // null (nicht 5!)

Variablen tauschen

let a = 1;
let b = 2;

// Ohne Destructuring
let temp = a;
a = b;
b = temp;

// Mit Destructuring - eine Zeile!
[a, b] = [b, a];

console.log(a);  // 2
console.log(b);  // 1

Verschachtelte Arrays

const matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

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

// Bestimmte Position
const [[, , eckeObenRechts]] = matrix;
console.log(eckeObenRechts);  // 3

Object Destructuring

Grundlagen

const person = {
    name: "Max",
    alter: 25,
    stadt: "Berlin"
};

// Ohne Destructuring
const name = person.name;
const alter = person.alter;
const stadt = person.stadt;

// Mit Destructuring
const { name, alter, stadt } = person;
console.log(name);   // "Max"
console.log(alter);  // 25
console.log(stadt);  // "Berlin"

Neue Variablennamen

const person = {
    name: "Max",
    alter: 25
};

// Umbenennen: { original: neuName }
const { name: personName, alter: personAlter } = person;
console.log(personName);   // "Max"
console.log(personAlter);  // 25

// Praktisch bei Konflikten
const name = "Lisa";  // Bereits vorhanden
const { name: userName } = person;
console.log(userName);  // "Max"

Default-Werte

const person = {
    name: "Max"
};

const { name, alter = 18, stadt = "Unbekannt" } = person;
console.log(name);   // "Max"
console.log(alter);  // 18 (Default)
console.log(stadt);  // "Unbekannt" (Default)

// Kombination: Umbenennen + Default
const { name: n, land: country = "Deutschland" } = person;
console.log(n);        // "Max"
console.log(country);  // "Deutschland"

Rest-Operator

const person = {
    name: "Max",
    alter: 25,
    stadt: "Berlin",
    beruf: "Entwickler"
};

const { name, ...rest } = person;
console.log(name);  // "Max"
console.log(rest);  // { alter: 25, stadt: "Berlin", beruf: "Entwickler" }

// Praktisch: Bestimmte Keys entfernen
const { beruf, ...ohneBeruf } = person;
console.log(ohneBeruf);  // { name, alter, stadt }

Verschachtelte Objekte

const user = {
    name: "Max",
    adresse: {
        stadt: "Berlin",
        plz: "10115",
        land: {
            name: "Deutschland",
            code: "DE"
        }
    }
};

// Verschachtelt destructuren
const {
    name,
    adresse: {
        stadt,
        land: { code }
    }
} = user;

console.log(name);   // "Max"
console.log(stadt);  // "Berlin"
console.log(code);   // "DE"

// Achtung: adresse ist NICHT definiert!
// console.log(adresse);  // ReferenceError

Computed Property Names

const key = "name";
const person = { name: "Max", alter: 25 };

const { [key]: wert } = person;
console.log(wert);  // "Max"

Destructuring in Funktionen

Parameter Destructuring

// Objekt als Parameter
function gruss({ name, alter }) {
    return `Hallo ${name}, du bist ${alter} Jahre alt`;
}

const person = { name: "Max", alter: 25 };
console.log(gruss(person));
// "Hallo Max, du bist 25 Jahre alt"

// Direkt im Aufruf
console.log(gruss({ name: "Lisa", alter: 30 }));

Mit Defaults

function createUser({
    name = "Gast",
    role = "user",
    active = true
} = {}) {  // = {} wichtig für optionale Parameter!
    return { name, role, active };
}

console.log(createUser());
// { name: "Gast", role: "user", active: true }

console.log(createUser({ name: "Max", role: "admin" }));
// { name: "Max", role: "admin", active: true }

Array Parameter

// Erste zwei Elemente
function summeErsteZwei([a, b]) {
    return a + b;
}

console.log(summeErsteZwei([1, 2, 3, 4]));  // 3

// Mit Rest
function summeAlle([erste, ...rest]) {
    return erste + rest.reduce((a, b) => a + b, 0);
}

console.log(summeAlle([1, 2, 3, 4]));  // 10

Return Value Destructuring

function getMinMax(zahlen) {
    return {
        min: Math.min(...zahlen),
        max: Math.max(...zahlen)
    };
}

const { min, max } = getMinMax([5, 2, 8, 1, 9]);
console.log(min, max);  // 1 9

// Bei Arrays
function getRange(zahlen) {
    return [Math.min(...zahlen), Math.max(...zahlen)];
}

const [minVal, maxVal] = getRange([5, 2, 8, 1, 9]);
console.log(minVal, maxVal);  // 1 9

Praktische Beispiele

API Response

const response = {
    data: {
        users: [
            { id: 1, name: "Max" },
            { id: 2, name: "Lisa" }
        ],
        total: 2,
        page: 1
    },
    status: 200,
    headers: {}
};

// Nur was wir brauchen
const {
    data: { users, total },
    status
} = response;

console.log(users);   // [{ id: 1, ... }, { id: 2, ... }]
console.log(total);   // 2
console.log(status);  // 200

React Props Pattern

// Typisches React Pattern
function UserCard({ name, email, avatar = "/default.png", onEdit }) {
    // name, email, avatar, onEdit direkt nutzbar
    return `<div>${name} (${email})</div>`;
}

// Event Handler
function handleClick({ target, currentTarget, preventDefault }) {
    preventDefault();
    console.log(target);
}

Import Destructuring

// Statt:
import lodash from 'lodash';
const map = lodash.map;
const filter = lodash.filter;

// Besser (wenn Modul es unterstützt):
import { map, filter, reduce } from 'lodash';

Loop mit Destructuring

const users = [
    { name: "Max", alter: 25 },
    { name: "Lisa", alter: 30 },
    { name: "Tom", alter: 20 }
];

// for...of mit Destructuring
for (const { name, alter } of users) {
    console.log(`${name} ist ${alter}`);
}

// forEach mit Destructuring
users.forEach(({ name }) => console.log(name));

// map mit Destructuring
const namen = users.map(({ name }) => name);

Object.entries mit Destructuring

const scores = { Max: 85, Lisa: 92, Tom: 78 };

for (const [name, score] of Object.entries(scores)) {
    console.log(`${name}: ${score} Punkte`);
}

// Filtern und transformieren
const bestanden = Object.entries(scores)
    .filter(([_, score]) => score >= 80)
    .map(([name, score]) => ({ name, score, passed: true }));

Häufige Patterns

Optionen-Objekt

function connect({
    host = "localhost",
    port = 3000,
    secure = false,
    timeout = 5000
} = {}) {
    const protocol = secure ? "https" : "http";
    console.log(`Connecting to ${protocol}://${host}:${port}`);
    return { host, port, secure, timeout };
}

// Nur überschreiben was nötig
connect({ port: 8080 });
// Connecting to http://localhost:8080

Clone & Modify

const original = { name: "Max", alter: 25, stadt: "Berlin" };

// Kopieren und ändern
const { alter, ...rest } = original;
const modified = { ...rest, alter: 26 };

console.log(modified);  // { name: "Max", stadt: "Berlin", alter: 26 }

Named Parameters

// Statt vieler Parameter in bestimmter Reihenfolge
function badFunction(a, b, c, d, e) { }
badFunction(1, null, null, null, 5);  // 😱

// Besser: Destructured Object
function goodFunction({ required, optionalA = 1, optionalB = 2 }) { }
goodFunction({ required: 5 });  // ✅

Conditional Destructuring

const maybeUser = null;

// Sicher mit Default
const { name = "Gast" } = maybeUser || {};
console.log(name);  // "Gast"

// Oder mit Optional Chaining + Nullish Coalescing
const userName = maybeUser?.name ?? "Gast";

Zusammenfassung

PatternSyntax
Arrayconst [a, b] = arr
Objectconst { x, y } = obj
Überspringenconst [, , third] = arr
Restconst [first, ...rest] = arr
Defaultconst { x = 10 } = obj
Umbenennenconst { x: newName } = obj
Verschachteltconst { a: { b } } = obj
Parameterfunction({ x, y }) {}
// Kombiniertes Beispiel
const {
    name,
    settings: {
        theme = "light",
        lang: language = "de"
    } = {},
    ...rest
} = userData;

Übung: Schreibe eine Funktion formatAddress, die ein verschachteltes Adress-Objekt nimmt und mit Destructuring eine formatierte Adresse als String zurückgibt:

const user = {
    name: "Max",
    address: {
        street: "Hauptstraße 1",
        city: "Berlin",
        zip: "10115",
        country: { name: "Deutschland", code: "DE" }
    }
};
// → "Max, Hauptstraße 1, 10115 Berlin, DE"