Kurs JavaScript i TypeScript · Moduł 2: Funkcje, tablice i obiekty
Destrukturyzacja obiektów i tablic
W tej lekcji8
Raport z laboratorium Parku Jurajskiego to obiekt pełen danych: parametry witalne, współrzędne GPS, wyniki analiz DNA. Żeby coś z nim zrobić, musisz wyciągać wartości jedna po drugiej: report.vitals.heartRate, report.location.zone i tak dalej, za każdym razem od nowa. "Destrukturyzacja to jak sortowanie próbek DNA" - mówi Dr. Rex. "Zamiast ręcznie wyciągać każdą probówkę, jednym ruchem bierzesz dokładnie te dane, których potrzebujesz."
Destrukturyzacja obiektów - podstawy
Destrukturyzacja obiektu wyciąga jego właściwości do osobnych zmiennych w jednej linii. Porównaj dwa zapisy:
1const dinosaur = {
2 name: 'Rex',
3 species: 'Tyrannosaurus',
4 weight: 8000,
5 zone: 'A'
6};
7
8// Bez destrukturyzacji
9const name1 = dinosaur.name;
10const weight1 = dinosaur.weight;
11
12// Z destrukturyzacją - znacznie krócej!
13const { name, species, weight, zone } = dinosaur;
14console.log(name); // "Rex"
15console.log(species); // "Tyrannosaurus"
16console.log(weight); // 8000Klamry po lewej stronie znaku = nie tworzą nowego obiektu. To wzorzec, który mówi: "utwórz zmienne o tych nazwach i wpisz do nich wartości właściwości o tych samych nazwach". Obiekt dinosaur zostaje nienaruszony, nic z niego nie znika ani nie przybywa.
Zmiana nazwy zmiennej (alias)
Czasem nazwa właściwości koliduje z istniejącą zmienną albo po prostu jest nieczytelna. Wtedy po dwukropku podajesz nową nazwę. Nie musisz też wyciągać wszystkich właściwości, tylko te potrzebne:
1const { name: dinoName, zone: dinoZone } = dinosaur;
2console.log(dinoName); // "Rex"
3console.log(dinoZone); // "A"Powstały tylko zmienne dinoName i dinoZone. Zmienne name i zone nie zostały przez ten zapis utworzone, bo nazwa przed dwukropkiem wskazuje jedynie, którą właściwość czytamy. Aliasów może być kilka naraz:
1const sensor = { id: 'S-001', value: 42.5, status: 'active' };
2
3// Zmieniamy nazwy zmiennych
4const { id: sensorId, value: reading, status: sensorStatus } = sensor;
5console.log(sensorId); // "S-001"
6console.log(reading); // 42.5
7console.log(sensorStatus); // "active"Czytaj dwukropek jako "zapisz do": id: sensorId znaczy "weź id i zapisz do sensorId".
Wartości domyślne
Jeśli właściwości brakuje w obiekcie, możesz ustawić wartość domyślną po znaku =. Alias i wartość domyślna łączą się w jednym zapisie:
1const specimen = { name: 'Blue', species: 'Velociraptor' };
2
3// health nie istnieje w obiekcie - użyj wartości domyślnej
4const { name: specimenName, health = 100, zone: specimenZone = 'Nieznana' } = specimen;
5console.log(specimenName); // "Blue"
6console.log(health); // 100 (domyślna)
7console.log(specimenZone); // "Nieznana" (domyślna)Wartość domyślna działa tylko wtedy, gdy właściwości brakuje albo ma wartość undefined. Gdyby obiekt miał health: 95, dostałbyś 95, a przy health: null dostałbyś null, bo null to celowo wpisana wartość.
Destrukturyzacja zagnieżdżona
Obiekty często zawierają zagnieżdżone struktury, a destrukturyzacja pozwala sięgnąć w głąb, powtarzając kształt obiektu:
1const dinoReport = {
2 name: 'Rex',
3 vitals: {
4 heartRate: 65,
5 temperature: 37.2,
6 bloodPressure: { systolic: 120, diastolic: 80 }
7 },
8 location: { zone: 'A', sector: 3 }
9};
10
11// Destrukturyzacja zagnieżdżona
12const {
13 name: reportName,
14 vitals: { heartRate, temperature },
15 location: { zone: reportZone, sector }
16} = dinoReport;
17
18console.log(reportName); // "Rex"
19console.log(heartRate); // 65
20console.log(temperature); // 37.2
21console.log(reportZone); // "A"
22console.log(sector); // 3Uwaga na częsty błąd: zapis vitals: { heartRate } nie tworzy zmiennej vitals, tylko wskazuje drogę do heartRate. Gdyby w raporcie zabrakło vitals, dostaniesz TypeError. Dlatego polecam schodzić najwyżej dwa poziomy w głąb, bo głębsze wzorce trudno czytać.
Destrukturyzacja tablic
Tablice destrukturyzujemy w nawiasach kwadratowych. Tu liczy się pozycja, a nie nazwa, więc zmienne możesz nazwać dowolnie:
1const dnaSequence = ['A', 'T', 'C', 'G', 'T', 'A'];
2
3// Wyciągamy pierwsze trzy elementy
4const [first, second, third] = dnaSequence;
5console.log(first); // "A"
6console.log(second); // "T"
7console.log(third); // "C"
8
9// Pomijanie elementów za pomocą przecinków
10const [, , thirdNucleotide, , fifthNucleotide] = dnaSequence;
11console.log(thirdNucleotide); // "C"
12console.log(fifthNucleotide); // "T"Każdy pusty przecinek przeskakuje jedną pozycję. W zapisie const [a, , b] = ['Rex', 'Blue', 'Delta'] zmienna a dostaje 'Rex', 'Blue' zostaje pominięte, a b dostaje 'Delta'.
Zamiana wartości zmiennych
Destrukturyzacja tablic pozwala elegancko zamienić wartości dwóch zmiennych bez zmiennej tymczasowej, na przykład gdy dwa dinozaury zamieniają się wybiegami:
1let zoneA = 'Rex';
2let zoneB = 'Blue';
3
4// Zamiana wartości
5[zoneA, zoneB] = [zoneB, zoneA];
6console.log(zoneA); // "Blue"
7console.log(zoneB); // "Rex"Prawa strona tworzy tymczasową tablicę ['Blue', 'Rex'], a lewa od razu ją rozpakowuje. Pilnuj średnika w linii poprzedzającej: linia zaczynająca się od [ bez niego sklei się z poprzednią i zamiana skończy się błędem.
Wartości domyślne w tablicach
Tablice też przyjmują wartości domyślne. Gdy czujnik GPS przysłał tylko jedną współrzędną, druga dostaje wartość zapasową:
1const coordinates = [12.5];
2const [latitude, longitude = 0] = coordinates;
3console.log(latitude); // 12.5
4console.log(longitude); // 0 (domyślna)Pozycja 1 w tablicy nie istnieje, więc longitude dostaje 0 zamiast undefined.
Destrukturyzacja w parametrach funkcji
Destrukturyzacja jest szczególnie przydatna w parametrach funkcji. Funkcja przyjmuje obiekt i od razu wybiera z niego potrzebne pola:
1// Destrukturyzacja obiektu w parametrze
2function displayDino({ name, species, weight = 'nieznana' }) {
3 console.log(`${name} (${species}) - ${weight} kg`);
4}
5
6displayDino({ name: 'Rex', species: 'T-Rex', weight: 8000 });
7// "Rex (T-Rex) - 8000 kg"
8
9displayDino({ name: 'Blue', species: 'Velociraptor' });
10// "Blue (Velociraptor) - nieznana kg"
11
12// Destrukturyzacja tablicy w parametrze
13function processCoords([lat, lon]) {
14 console.log(`Szerokość: ${lat}, Długość: ${lon}`);
15}
16
17processCoords([12.345, 67.890]);
18// "Szerokość: 12.345, Długość: 67.89"Kolejność pól w przekazanym obiekcie nie ma znaczenia, a wywołanie samo opisuje, co jest czym. Dlatego polecam ten zapis, gdy funkcja ma więcej niż dwa parametry. Zauważ też, że liczba 67.890 wypisuje się jako 67.89, bo zamiana liczby na tekst pomija końcowe zera. Wywołanie displayDino() bez argumentu rzuci TypeError, więc gdy obiekt jest opcjonalny, dopisz domyślne = {} za wzorcem.
Łączenie destrukturyzacji z resztą (rest)
Operator ... zbiera "resztę" elementów do nowej tablicy albo nowego obiektu:
1const allSpecies = ['T-Rex', 'Velociraptor', 'Triceratops', 'Brachio', 'Stego'];
2
3const [firstSpecies, secondSpecies, ...otherSpecies] = allSpecies;
4console.log(firstSpecies); // "T-Rex"
5console.log(secondSpecies); // "Velociraptor"
6console.log(otherSpecies); // ["Triceratops", "Brachio", "Stego"]
7
8// Rest w obiektach
9const fullDino = { name: 'Rex', species: 'T-Rex', weight: 8000, zone: 'A', health: 95 };
10const { name: restName, ...dinoStats } = fullDino;
11console.log(restName); // "Rex"
12console.log(dinoStats); // { species: "T-Rex", weight: 8000, zone: "A", health: 95 }Rest musi stać na końcu wzorca, a fullDino nadal ma wszystkie pięć właściwości. W następnej lekcji zobaczysz, że te same trzy kropki potrafią też rozpakowywać dane.
Praktyka
W piaskownicy czekają destrukturyzacja obiektu, aliasy z wartościami domyślnymi i zagnieżdżony raport. Dopisz własne wzorce i sprawdź w konsoli, które zmienne powstały.
Kod do tej lekcji: index.js
1// === DESTRUKTURYZACJA OBIEKTÓW I TABLIC ===
2
3// 1. Destrukturyzacja obiektu
4const dinosaur = { name: 'Rex', species: 'Tyrannosaurus', weight: 8000, zone: 'A' };
5const { name, species, weight } = dinosaur;
6console.log('=== Obiekt ===');
7console.log('Imię:', name, '| Gatunek:', species, '| Waga:', weight);
8
9// 2. Zmiana nazwy (alias) i wartości domyślne
10const sensor = { id: 'S-001', value: 42.5 };
11const { id: sensorId, value: reading, status: sensorStatus = 'active' } = sensor;
12console.log('\n=== Alias i domyślne ===');
13console.log('ID:', sensorId, '| Odczyt:', reading, '| Status:', sensorStatus);
14
15// 3. Destrukturyzacja zagnieżdżona
16const report = {
17 name: 'Rex',
18 vitals: { heartRate: 65, temperature: 37.2 },
19 location: { zone: 'A', sector: 3 }
20};
21const { vitals: { heartRate, temperature }, location: { zone } } = report;
22console.log('\n=== Zagnieżdżona ===');
23console.log('Puls:', heartRate, '| Temp:', temperature, '| Strefa:', zone);
24
25// 4. Destrukturyzacja tablicy
26const dna = ['A', 'T', 'C', 'G', 'T', 'A'];
27const [first, second, third] = dna;
28console.log('\n=== Tablica ===');
29console.log('Pierwsze 3:', first, second, third);
30
31// Pomijanie elementów
32const [, , thirdEl, , fifthEl] = dna;
33console.log('Trzeci:', thirdEl, '| Piąty:', fifthEl);
34
35// 5. Zamiana wartości
36let zoneA = 'Rex';
37let zoneB = 'Blue';
38[zoneA, zoneB] = [zoneB, zoneA];
39console.log('\n=== Zamiana ===');
40console.log('zoneA:', zoneA, '| zoneB:', zoneB);
41
42// 6. Destrukturyzacja w parametrach funkcji
43function displayDino({ name: n, species: s, weight: w = 'nieznana' }) {
44 console.log(n + ' (' + s + ') - ' + w + ' kg');
45}
46console.log('\n=== Parametry funkcji ===');
47displayDino({ name: 'Rex', species: 'T-Rex', weight: 8000 });
48displayDino({ name: 'Blue', species: 'Velociraptor' });
49
50// 7. Rest w destrukturyzacji
51const all = { name: 'Rex', species: 'T-Rex', weight: 8000, zone: 'A', health: 95 };
52const { name: dName, ...stats } = all;
53console.log('\n=== Rest ===');
54console.log('Imię:', dName);
55console.log('Reszta:', JSON.stringify(stats));Pamiętaj: destrukturyzacja to sortownia próbek, która jednym ruchem przenosi potrzebne probówki na stół, a oryginalny raport zostawia nienaruszony.
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Co robi zapis const { name, weight } = dinosaur?
2. Co oznacza zapis const { id: sensorId, status = 'active' } = sensor?
3. Jak zamienić wartości dwóch zmiennych za pomocą destrukturyzacji tablicy?
Zadania praktyczne w grze
- Edytor kodu
Masz obiekt const dino = { name: 'Rex', species: 'T-Rex', stats: { weight: 8000, speed: 30 } } i tablicę const zones = ['A', 'B', 'C', 'D']. Destrukturyzacją obiektu utwórz zmienne dinoName (alias dla name), species, weight (z zagnieżdżonego stats) i diet z wartością domyślną 'carnivore'. Destrukturyzacją tablicy utwórz firstZone, secondZone i otherZones z resztą elementów. Napisz też funkcję describeDino({ name, species }), która destrukturyzuje parametr i zwraca tekst name + ' (' + species + ')'.
- Układanie w pionie
Uporządkuj, co zostanie przypisane do zmiennych w destrukturyzacji const [a, , b] = ['Rex', 'Blue', 'Delta']:
- Klikanie w kolejności
Ułóż elementy destrukturyzacji zagnieżdżonej: const { vitals: { heartRate } } = report
- Edytor kodu
Masz raport: const report = { id: 'R-7', dino: { name: 'Blue', vitals: { heartRate: 65, temperature: 37.2 } }, zone: 'B', status: 'ok' }. Destrukturyzacją utwórz: id, patientName (alias dla report.dino.name), heartRate (z report.dino.vitals) oraz obiekt meta, który operatorem rest zbierze pozostałe właściwości najwyższego poziomu (bez id i dino). Napisz też funkcję formatVitals({ heartRate, temperature = 36.6 }), która zwraca tekst heartRate + ' bpm, ' + temperature + ' C'.