Temat 21 · 2 × 45 min
Składnia ES6+ na co dzień
Do tej pory pisałeś kod, który musi działać na egzaminie i który egzaminator ma przeczytać bez zaskoczeń. Od tej lekcji wchodzisz w warstwę „ponad egzamin”: składnię, którą zobaczysz w każdym współczesnym projekcie, w dokumentacji bibliotek, w kodzie React i w zadaniach INF.04. Większość z niej pojawiła się w standardzie ES2015 (czyli „ES6”) i w kolejnych latach, stąd nazwa „ES6+”. Nie uczysz się tu nowych pojęć, tylko krótszych i bezpieczniejszych zapisów rzeczy, które już umiesz: składania napisów, wyciągania danych z obiektów i tablic, przekazywania argumentów i sprawdzania, czy coś istnieje.
Template stringi – pogłębienie
Template string (szablon napisu) znasz z lekcji o napisach: piszesz go w odwrotnych apostrofach `, a wyrażenia wstawiasz w ${…}. Trzy rzeczy, których zwykle używa się za mało:
- W
${…}może być dowolne wyrażenie – działanie, wywołanie funkcji, operator warunkowy?:. Nie tylko nazwa zmiennej. - Template string może mieć wiele linii – znaki nowej linii zostają w napisie. To wygodne przy budowaniu fragmentów HTML.
- Template stringi można zagnieżdżać – wewnątrz
${…}może być kolejny template string, np. wmap().
Co wypisze ten kod?
const cena = 49.9;
const ilosc = 3;
console.log(`Razem: ${(cena * ilosc).toFixed(2)} zł`);const produkt = { nazwa: 'Słuchawki', cena: 149.9, promocja: true };
// 1. wyrażenia w ${…}: działanie, operator ?:
const etykieta = `${produkt.nazwa} – ${produkt.cena.toFixed(2)} zł${produkt.promocja ? ' (PROMOCJA)' : ''}`;
console.log(etykieta);
// 2. wiele linii – nowe linie zostają w napisie
const karta = `
<article class="produkt">
<h3>${produkt.nazwa}</h3>
<p>${produkt.cena} zł</p>
</article>`;
console.log(karta.trim());
// 3. zagnieżdżenie: lista <li> z tablicy
const oceny = [5, 4, 3];
console.log(`<ul>${oceny.map((o) => `<li>${o}</li>`).join('')}</ul>`);Parametry domyślne
Zamiast sprawdzać w ciele funkcji, czy argument został podany, wpisujesz wartość domyślną wprost w nagłówku. Domyślna wartość jest używana wtedy, gdy argument jest undefined – czyli pominięty albo przekazany jako undefined. Dla null, 0 czy "" nie zadziała, bo to są konkretne, przekazane wartości.
function obliczBrutto(netto, vat = 23) {
return netto * (1 + vat / 100);
}
console.log(obliczBrutto(100)); // vat pominięty → 23
console.log(obliczBrutto(100, 8)); // vat podany → 8
console.log(obliczBrutto(100, 0)); // 0 to konkretna wartość, nie „brak”
console.log(obliczBrutto(100, undefined)); // undefined → wraca domyślne 23
// wartość domyślna może być wyrażeniem i korzystać z wcześniejszych parametrów
function powitaj(imie = 'Gościu', tekst = `Cześć, ${imie}!`) {
return tekst;
}
console.log(powitaj());
console.log(powitaj('Ola'));
console.log(powitaj('Ola', 'Dzień dobry'));Destrukturyzacja tablic
Destrukturyzacja (destructuring) to „rozpakowanie” wartości z tablicy lub obiektu prosto do zmiennych. Zamiast trzech linii const a = tab[0]; const b = tab[1]; … piszesz jedną. Po lewej stronie = stawiasz wzór w nawiasach kwadratowych, który wygląda jak tablica.
const data = '2026-10-20'.split('-');
const [rok, miesiac, dzien] = data;
console.log(rok, miesiac, dzien);
// pomijanie elementów – zostaw puste miejsce
const [, , tylkoDzien] = data;
console.log(tylkoDzien);
// wartości domyślne, gdy elementu brakuje
const [pierwszy, drugi = 'brak'] = ['jeden'];
console.log(pierwszy, drugi);
// reszta elementów do nowej tablicy
const [zwyciezca, ...pozostali] = ['Ala', 'Bartek', 'Celina', 'Darek'];
console.log(zwyciezca, pozostali);
// zamiana wartości dwu zmiennych bez zmiennej pomocniczej
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b);Destrukturyzacja tablicowa działa ze wszystkim, co da się iterować – także z napisem (const [p, d] = 'ab') czy z wynikiem Object.entries(), który zobaczysz niżej.
Destrukturyzacja obiektów
Dla obiektów wzór piszesz w klamrach, a zmienne dobierają się po nazwie właściwości, nie po kolejności. To najczęściej używana forma – praktycznie każdy kod React czy Node zaczyna się od const { … } = ….
Co wypisze ten kod?
const uczen = { imie: 'Kasia', klasa: '3TP', srednia: 4.6 };
const { klasa, imie, szkola = 'ZST' } = uczen;
console.log(imie, klasa, szkola);const uczen = {
imie: 'Kasia',
klasa: '3TP',
oceny: { informatyka: 5, matematyka: 4 },
};
// podstawowo: nazwy zmiennych = nazwy właściwości
const { imie, klasa } = uczen;
console.log(imie, klasa);
// zmiana nazwy: wlasciwosc: nowaNazwa
const { imie: pierwszeImie } = uczen;
console.log(pierwszeImie);
// wartość domyślna i zmiana nazwy razem
const { srednia: sredniaOcen = 0 } = uczen;
console.log(sredniaOcen);
// zagnieżdżenie
const { oceny: { informatyka } } = uczen;
console.log(informatyka);
// reszta właściwości do nowego obiektu
const { klasa: k, ...bezKlasy } = uczen;
console.log(k, bezKlasy);Destrukturyzacja w parametrach funkcji
Najpraktyczniejsze zastosowanie: funkcja przyjmuje jeden obiekt z opcjami zamiast pięciu argumentów, których kolejność trzeba pamiętać. W nagłówku rozpakowujesz tylko to, czego potrzebujesz, i od razu ustawiasz wartości domyślne.
function zamowBilet({ film, miejsce, ulga = false, godzina = '18:00' }) {
const cena = ulga ? 18 : 26;
return `${film}, ${godzina}, miejsce ${miejsce}: ${cena} zł`;
}
console.log(zamowBilet({ film: 'Diuna', miejsce: 'C12' }));
console.log(zamowBilet({ miejsce: 'A1', ulga: true, film: 'Shrek', godzina: '16:30' }));
// to samo dla tablic: funkcja dostaje parę [klucz, wartość]
const pokazWpis = ([klucz, wartosc]) => `${klucz} = ${wartosc}`;
console.log(pokazWpis(['motyw', 'ciemny']));Spread: rozsypywanie tablic i obiektów
Trzy kropki ... po prawej stronie (w wywołaniu, w literale tablicy lub obiektu) to spread – „rozsyp elementy w to miejsce”. Robi płytką kopię, łączy kolekcje i zamienia tablicę w listę argumentów.
const podstawowe = ['HTML', 'CSS'];
const zaawansowane = ['JS', 'PHP'];
// łączenie i kopiowanie tablic
const wszystkie = [...podstawowe, ...zaawansowane, 'SQL'];
console.log(wszystkie);
const kopia = [...podstawowe];
kopia.push('Sass');
console.log(podstawowe, kopia); // oryginał nietknięty
// tablica → lista argumentów
const punkty = [12, 45, 7, 31];
console.log(Math.max(...punkty)); // zamiast Math.max(12, 45, 7, 31)
// obiekty: kopia z nadpisaniem – późniejsze wygrywa
const domyslne = { motyw: 'jasny', jezyk: 'pl', dzwiek: true };
const uzytkownika = { motyw: 'ciemny' };
const ustawienia = { ...domyslne, ...uzytkownika };
console.log(ustawienia);
// „zmień jedno pole, nie dotykając oryginału” – wzorzec z React
const produkt = { nazwa: 'Mysz', cena: 89 };
const przeceniony = { ...produkt, cena: 69 };
console.log(produkt.cena, przeceniony.cena);Spread kopiuje płytko: jeśli w obiekcie siedzi inny obiekt lub tablica, kopia i oryginał nadal dzielą tę zagnieżdżoną część. Dokładnie o tym jest lekcja o referencjach.
Rest: zbieranie argumentów
Te same trzy kropki po lewej stronie (w parametrach funkcji lub we wzorze destrukturyzacji) to rest – „zebrać resztę do tablicy”. Dzięki temu funkcja może przyjmować dowolną liczbę argumentów i dostaje je jako prawdziwą tablicę z length, map, reduce itd. Rest musi być ostatni – function f(...a, b) to błąd składni.
function suma(...liczby) {
let wynik = 0;
for (const n of liczby) wynik += n;
return wynik;
}
console.log(suma());
console.log(suma(5));
console.log(suma(1, 2, 3, 4));
// parametry zwykłe + reszta
function zapiszOcene(przedmiot, ...oceny) {
return `${przedmiot}: ${oceny.length} ocen, ostatnia ${oceny.at(-1)}`;
}
console.log(zapiszOcene('fizyka', 3, 4, 5));
// spread i rest razem: tablica → argumenty → tablica
const wyniki = [88, 92, 79];
console.log(suma(...wyniki));Optional chaining ?. – bezpieczne sięganie w głąb
Dane z formularza, z localStorage czy z API często mają dziury: brak adresu, brak drugiej oceny, element nieznaleziony w DOM. Zwykły zapis uzytkownik.adres.miasto wyrzuci TypeError, gdy adres jest undefined. Operator ?. (optional chaining) mówi: „jeśli to, co po lewej, jest null lub undefined, zatrzymaj się i daj undefined zamiast błędu”.
const zamowienie = {
nr: 1042,
klient: { imie: 'Marek' },
// brak: dostawa, rabat, anuluj()
};
console.log(zamowienie.klient?.imie); // Marek
console.log(zamowienie.dostawa?.miasto); // undefined, bez błędu
console.log(zamowienie.dostawa?.miasto?.toUpperCase()); // też undefined
// wywołanie metody, która może nie istnieć
console.log(zamowienie.anuluj?.()); // undefined – nic się nie wywołało
// dostęp nawiasowy
const pole = 'klient';
console.log(zamowienie[pole]?.imie);
// typowy przypadek w DOM: element może nie istnieć
const element = null; // np. wynik document.querySelector('#brak')
console.log(element?.textContent); // undefined zamiast TypeErrorNullish coalescing ?? – wartość domyślna bez pułapki zera
Operator ?? zwraca prawą stronę tylko wtedy, gdy lewa jest null lub undefined. Tym różni się od ||, który zwraca prawą stronę dla każdej wartości fałszywej: także dla 0, "", false i NaN. Przy liczbach i napisach z formularza ta różnica rozstrzyga o poprawności programu.
Co wypisze ten kod?
const ilosc = 0;
const nazwa = '';
console.log(ilosc || 10, ilosc ?? 10);
console.log(nazwa || 'brak', nazwa ?? 'brak');const koszyk = { sztuk: 0, uwagi: '', rabat: null };
console.log(koszyk.sztuk || 1); // 1 – ZŁE: użytkownik wpisał 0, a my zmieniliśmy na 1
console.log(koszyk.sztuk ?? 1); // 0 – dobrze: 0 to prawdziwa wartość
console.log(koszyk.uwagi || '(brak uwag)'); // tu || ma sens: pusty napis = brak uwag
console.log(koszyk.rabat ?? 0); // 0 – null oznacza „nie ustawiono”
// ?. i ?? razem – klasyczna para
const ustawienia = {};
const motyw = ustawienia.wyglad?.motyw ?? 'jasny';
console.log(motyw);
// przypisanie tylko, gdy brak wartości: ??= (ES2021)
const konfiguracja = { port: 0 };
konfiguracja.port ??= 8080; // 0 nie jest null → zostaje 0
konfiguracja.host ??= 'localhost'; // brak → ustawia
console.log(konfiguracja);Zasada kciuka: ?? dla liczb i wartości, które mogą być legalnie zerem lub pustym napisem, || tylko tam, gdzie chcesz świadomie traktować wszystko „puste” jednakowo. Uwaga składniowa: ?? nie wolno mieszać z &&/|| w jednym wyrażeniu bez nawiasów – silnik odrzuci taki kod jako błąd składni.
Pętla for…of i wpisy obiektu
for…of przechodzi po wartościach wszystkiego, co iterowalne: tablic, napisów, Map, Set, kolekcji DOM z querySelectorAll. Jest czytelniejsza niż for z indeksem, gdy indeks nie jest potrzebny, i – w odróżnieniu od forEach – pozwala użyć break, continue i await.
Obiekt zwykły nie jest iterowalny, ale Object.keys(), Object.values() i Object.entries() zamieniają go na tablice, po których już można iterować. Z entries w naturalny sposób łączy się destrukturyzacja pary [klucz, wartosc].
const oceny = [5, 3, 4, 2, 5];
let suma = 0;
for (const ocena of oceny) suma += ocena;
console.log(`Średnia: ${(suma / oceny.length).toFixed(2)}`);
// break działa (w forEach by nie zadziałał)
for (const ocena of oceny) {
if (ocena < 3) {
console.log('Jest ocena niedostateczna – przerywam');
break;
}
}
// indeks potrzebny? entries() tablicy daje pary [indeks, wartość]
for (const [i, ocena] of oceny.entries()) {
if (i < 2) console.log(`#${i + 1}: ${ocena}`);
}
// obiekt → wpisy
const cennik = { laminowane: 12, winylowe: 14, deska: 18 };
for (const [rodzaj, cena] of Object.entries(cennik)) {
console.log(`${rodzaj}: ${cena} zł/m²`);
}
console.log(Object.keys(cennik), Object.values(cennik));Skrócone zapisy obiektów
ES6 skrócił trzy często powtarzane wzory w literale obiektu:
| Zapis | Przed ES6 | ES6+ |
|---|---|---|
| właściwość ze zmiennej o tej samej nazwie | { imie: imie, wiek: wiek } | { imie, wiek } |
| metoda | { przedstaw: function () { … } } | { przedstaw() { … } } |
| klucz obliczany z wyrażenia | obj[klucz] = w; po utworzeniu | { [klucz]: w } |
const imie = 'Tomek';
const wiek = 18;
const pole = 'klasa';
const uczen = {
imie, // zamiast imie: imie
wiek,
[pole]: '4TP', // klucz obliczany: właściwość klasa
[`ocena_${2026}`]: 5, // klucz z template stringa
przedstaw() { // skrócona metoda
return `${this.imie}, ${this.wiek} lat, ${this.klasa}`;
},
};
console.log(uczen.przedstaw());
console.log(Object.keys(uczen));
// funkcja strzałkowa zwracająca obiekt – klamry trzeba otoczyć nawiasami
const zrobPunkt = (x, y) => ({ x, y });
console.log(zrobPunkt(3, 4));Ściąga
| Składnia | Co robi | Przykład |
|---|---|---|
`…${wyr}…` | napis z wyrażeniem, może mieć wiele linii | `Razem: ${(a * b).toFixed(2)} zł` |
function f(x, y = 10) | parametr domyślny – gdy argument undefined | f(5) → y === 10 |
const [a, b] = tab | destrukturyzacja tablicy (po kolejności) | const [rok, mies] = '2026-10'.split('-') |
const [a, , c] = tab | pominięcie elementu | const [, drugi] = ['x', 'y'] |
const { p, q = 1 } = obj | destrukturyzacja obiektu (po nazwie) z domyślną | const { imie, wiek = 0 } = uczen |
const { p: nowa } = obj | zmiana nazwy zmiennej | const { imie: pierwsze } = uczen |
f({ a, b }) | destrukturyzacja w parametrze | function f({ film, ulga = false }) {} |
[...a, ...b], { ...o, x: 1 } | spread: kopia/łączenie/nadpisanie | const ustaw = { ...domyslne, ...moje } |
Math.max(...tab) | spread: tablica → argumenty | Math.min(...ceny) |
function f(...args) | rest: argumenty → tablica (ostatni) | suma(1, 2, 3) → args = [1, 2, 3] |
const [x, ...reszta] = tab | rest w destrukturyzacji | [1, 2, 3] → x = 1, reszta = [2, 3] |
obj?.p, obj?.[k], f?.() | undefined zamiast błędu, gdy po lewej null/undefined | dane.adres?.miasto |
a ?? b | b tylko, gdy a jest null/undefined | ilosc ?? 1 (zostawia 0) |
a || b | b, gdy a fałszywe (też 0, "") | uwagi || '(brak)' |
x ??= w | przypisz, jeśli x jest null/undefined | cfg.host ??= 'localhost' |
for (const x of tab) | pętla po wartościach iterowalnego | for (const li of lista.children) |
Object.entries(obj) | tablica par [klucz, wartosc] | for (const [k, v] of Object.entries(o)) |
{ a, b } | skrócona właściwość | zamiast { a: a, b: b } |
{ m() {} } | skrócona metoda | { licz() { return 1; } } |
{ [wyr]: w } | klucz obliczany | { [pole]: true }, { ['id_' + n]: 1 } |
() => ({ a: 1 }) | strzałka zwracająca obiekt | bez nawiasów zwróci undefined |
Zadania
Karta ucznia
Masz obiekt:
const uczen = {
imie: 'Zosia',
nazwisko: 'Nowak',
klasa: '3TP',
oceny: { informatyka: 5, angielski: 4 },
};Jedną instrukcją destrukturyzacji wyciągnij imie, nazwisko, klasa, ocenę z informatyki do zmiennej inf oraz nieistniejącą właściwość szkola z wartością domyślną 'ZST'. Następnie template stringiem wypisz: Zosia Nowak (3TP, ZST) – informatyka: 5. Nie używaj zapisu uczen.cos poza destrukturyzacją.
Pokaż rozwiązanie
const uczen = {
imie: 'Zosia',
nazwisko: 'Nowak',
klasa: '3TP',
oceny: { informatyka: 5, angielski: 4 },
};
// zagnieżdżona destrukturyzacja ze zmianą nazwy (informatyka → inf)
// i wartością domyślną dla brakującej właściwości
const {
imie,
nazwisko,
klasa,
oceny: { informatyka: inf },
szkola = 'ZST',
} = uczen;
console.log(`${imie} ${nazwisko} (${klasa}, ${szkola}) – informatyka: ${inf}`);Statystyki z dowolnej liczby ocen
Napisz funkcję statystyki(przedmiot, ...oceny), która przyjmuje nazwę przedmiotu i dowolną liczbę ocen, a zwraca obiekt { przedmiot, liczba, min, max, srednia } (średnia zaokrąglona do 2 miejsc, jako liczba). Użyj rest w parametrach, spread przy Math.min/Math.max i skróconych właściwości. Gdy ocen nie podano, funkcja ma zwrócić { przedmiot, liczba: 0, min: null, max: null, srednia: null } – bez Infinity i bez NaN.
Sprawdź: statystyki('matematyka', 3, 5, 4, 4) → { przedmiot: 'matematyka', liczba: 4, min: 3, max: 5, srednia: 4 }.
Pokaż rozwiązanie
function statystyki(przedmiot, ...oceny) {
const liczba = oceny.length;
// Math.min() bez argumentów daje Infinity, a 0/0 daje NaN – obsługujemy osobno
if (liczba === 0) {
return { przedmiot, liczba, min: null, max: null, srednia: null };
}
const min = Math.min(...oceny);
const max = Math.max(...oceny);
let suma = 0;
for (const o of oceny) suma += o;
const srednia = Number((suma / liczba).toFixed(2));
return { przedmiot, liczba, min, max, srednia }; // skrócone właściwości
}
console.log(statystyki('matematyka', 3, 5, 4, 4));
console.log(statystyki('fizyka', 2, 5));
console.log(statystyki('chemia'));
// rest i spread współpracują z gotową tablicą
const ocenyZDziennika = [4, 4, 5, 3, 6];
console.log(statystyki('informatyka', ...ocenyZDziennika));Kalkulator rat w ES6+
To zadanie z wzorca „kalkulator” przepisane na nowoczesną składnię. Cennik kursów trzymaj w obiekcie cennik = { excel: 300, grafika: 450, programowanie: 600 }. Funkcja obliczRaty({ kursy, raty = 1, miasto = 'Warszawie' }) przyjmuje obiekt z tablicą nazw wybranych kursów, liczbą rat i miastem, a zwraca napis dokładnie w formacie:
Kurs odbędzie się w Warszawie. Koszt całkowity: 750 zł. Płacisz 3 raty po 250 zł.
Wymagania: destrukturyzacja parametru z wartościami domyślnymi, for…of po tablicy kursów, ?? 0 dla kursu, którego nie ma w cenniku, template string. Formę „w Warszawie” uprość do „w ” + nazwa miejscownika, podanego w wywołaniu (np. miasto: 'Krakowie').
Pokaż rozwiązanie
const cennik = { excel: 300, grafika: 450, programowanie: 600 };
function obliczRaty({ kursy, raty = 1, miasto = 'Warszawie' }) {
let koszt = 0;
for (const nazwa of kursy) {
koszt += cennik[nazwa] ?? 0; // nieznany kurs nie psuje sumy (undefined dałoby NaN)
}
const rata = Math.round((koszt / raty) * 100) / 100;
return `Kurs odbędzie się w ${miasto}. Koszt całkowity: ${koszt} zł. Płacisz ${raty} raty po ${rata} zł.`;
}
console.log(obliczRaty({ kursy: ['excel', 'grafika'], raty: 3 }));
console.log(obliczRaty({ kursy: ['programowanie'], miasto: 'Krakowie' }));
console.log(obliczRaty({ kursy: ['excel', 'fotografia'], raty: 2, miasto: 'Gdańsku' }));W wersji z formularzem nazwy kursów zbierzesz z zaznaczonych checkboxów ([...document.querySelectorAll('input[name=kurs]:checked')].map((c) => c.value)), a obiekt opcji zbudujesz skróconymi właściwościami: obliczRaty({ kursy, raty, miasto }).
Scalanie ustawień użytkownika
Aplikacja ma ustawienia domyślne i ustawienia zapisane przez użytkownika, które mogą być niekompletne albo w ogóle nie istnieć (null):
const domyslne = { motyw: 'jasny', rozmiarCzcionki: 16, powiadomienia: { email: true, push: false } };
const zapisane = { rozmiarCzcionki: 0, powiadomienia: { push: true } };Napisz funkcję scal(domyslne, zapisane), która zwraca nowy obiekt (oryginałów nie zmienia), w którym wartości użytkownika nadpisują domyślne, a zagnieżdżony obiekt powiadomienia jest scalany osobno (żeby email: true nie zginęło). Funkcja ma działać także dla scal(domyslne, null). Zastanów się: czy rozmiarCzcionki: 0 ma zostać zerem? Co by zrobił ||?
Pokaż rozwiązanie
const domyslne = {
motyw: 'jasny',
rozmiarCzcionki: 16,
powiadomienia: { email: true, push: false },
};
const zapisane = { rozmiarCzcionki: 0, powiadomienia: { push: true } };
function scal(domyslne, zapisane) {
// null/undefined → pusty obiekt; ?? zostawia inne wartości bez zmian
const uzytkownika = zapisane ?? {};
return {
...domyslne,
...uzytkownika,
// zagnieżdżenie scalamy osobno – zwykły spread podmieniłby cały obiekt
powiadomienia: { ...domyslne.powiadomienia, ...uzytkownika.powiadomienia },
};
}
console.log(scal(domyslne, zapisane));
// rozmiarCzcionki zostaje 0, bo spread kopiuje wartość taką, jaka jest
// (z „||” napisalibyśmy zapisane.rozmiarCzcionki || 16 i zero by zginęło)
console.log(scal(domyslne, null));
console.log(domyslne.powiadomienia); // oryginał nietkniętySpread ...uzytkownika.powiadomienia z wartością undefined (gdy użytkownik nie zapisał powiadomień) jest bezpieczny – spread undefined w literale obiektu po prostu nic nie dodaje.
Podsumowanie zamówienia z dziurawych danych
Dane zamówienia przychodzą z API i bywają niekompletne. Napisz funkcję podsumuj(zamowienie), która dla każdego z poniższych wejść zwróci poprawny, jednolinijkowy napis i nigdy nie wyrzuci błędu:
const z1 = { nr: 7, klient: { imie: 'Ewa', adres: { miasto: 'Łódź' } }, pozycje: [{ nazwa: 'Kabel', cena: 20, ilosc: 2 }, { nazwa: 'Mysz', cena: 80 }] };
const z2 = { nr: 8, klient: { imie: 'Jan' }, pozycje: [] };
const z3 = { nr: 9 };Format: Zamówienie 7 dla Ewa (Łódź): 2 pozycje, razem 120 zł. Brak miasta → (miasto nieznane), brak klienta → dla nieznanego klienta, brak pozycje → traktuj jak pustą tablicę, brak ilosc → 1. Użyj ?., ??, destrukturyzacji z domyślnymi, for…of i template stringa.
Pokaż rozwiązanie
function podsumuj(zamowienie) {
// destrukturyzacja z domyślnymi: brak pozycji = pusta tablica
const { nr, klient, pozycje = [] } = zamowienie;
// ?. zatrzymuje się na pierwszym null/undefined, ?? daje tekst zastępczy
const imie = klient?.imie ?? 'nieznanego klienta';
const miasto = klient?.adres?.miasto ?? 'miasto nieznane';
let razem = 0;
for (const { cena = 0, ilosc = 1 } of pozycje) {
razem += cena * ilosc;
}
const slowo = pozycje.length === 1 ? 'pozycja' : pozycje.length >= 2 && pozycje.length <= 4 ? 'pozycje' : 'pozycji';
return `Zamówienie ${nr} dla ${imie} (${miasto}): ${pozycje.length} ${slowo}, razem ${razem} zł`;
}
const z1 = {
nr: 7,
klient: { imie: 'Ewa', adres: { miasto: 'Łódź' } },
pozycje: [{ nazwa: 'Kabel', cena: 20, ilosc: 2 }, { nazwa: 'Mysz', cena: 80 }],
};
const z2 = { nr: 8, klient: { imie: 'Jan' }, pozycje: [] };
const z3 = { nr: 9 };
console.log(podsumuj(z1));
console.log(podsumuj(z2));
console.log(podsumuj(z3));Zwróć uwagę na for (const { cena = 0, ilosc = 1 } of pozycje) – destrukturyzacja działa bezpośrednio w nagłówku pętli, a wartości domyślne załatwiają brakującą ilosc.
Test powtórkowy
Test powtórkowy
Składnia ES6+: 10 pytań, jedna poprawna odpowiedź.
Co wypisze ten kod?
const [a, , c = 10] = [1, 2];
console.log(a, c);Które wyrażenie zwróci 0, gdy const x = 0?
Co wypisze ten kod?
const a = { x: 1, y: 2 };
const b = { ...a, y: 20, z: 30 };
console.log(b.y, a.y, Object.keys(b).length);Który nagłówek funkcji jest poprawny?
Co wypisze ten kod?
const dane = { uczen: null };
console.log(dane.uczen?.imie, dane.klasa?.nazwa);Co zwróci wywołanie f()?
const f = () => { nazwa: 'Ala' };Co wypisze ten kod?
function cena(netto, vat = 23) {
return netto + netto * vat / 100;
}
console.log(cena(100, null), cena(100, undefined));Co wypisze ten kod?
const cennik = { kawa: 12, herbata: 9 };
for (const [nazwa, cena] of Object.entries(cennik)) {
console.log(nazwa + ':' + cena);
}Które wywołanie poprawnie przekaże elementy tablicy t = [3, 9, 1] jako osobne argumenty do Math.max?
Co wypisze ten kod?
const klucz = 'poziom';
const n = 2;
const obj = { [klucz]: 'trudny', [`etap${n}`]: true };
console.log(Object.keys(obj));