Przejdź do treści

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:

  1. W ${…} może być dowolne wyrażenie – działanie, wywołanie funkcji, operator warunkowy ?:. Nie tylko nazwa zmiennej.
  2. Template string może mieć wiele linii – znaki nowej linii zostają w napisie. To wygodne przy budowaniu fragmentów HTML.
  3. Template stringi można zagnieżdżać – wewnątrz ${…} może być kolejny template string, np. w map().
Sprawdź się

Co wypisze ten kod?

const cena = 49.9;
const ilosc = 3;
console.log(`Razem: ${(cena * ilosc).toFixed(2)} zł`);
szablony.js
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>`);
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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.

domyslne.js
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'));
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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.

destrukturyzacja-tablic.js
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);
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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 { … } = ….

Sprawdź się

Co wypisze ten kod?

const uczen = { imie: 'Kasia', klasa: '3TP', srednia: 4.6 };
const { klasa, imie, szkola = 'ZST' } = uczen;
console.log(imie, klasa, szkola);
destrukturyzacja-obiektow.js
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);
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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.

opcje.js
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']));
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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.

spread.js
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);
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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.

rest.js
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));
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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”.

optional-chaining.js
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 TypeError
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

Nullish 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.

Sprawdź się

Co wypisze ten kod?

const ilosc = 0;
const nazwa = '';
console.log(ilosc || 10, ilosc ?? 10);
console.log(nazwa || 'brak', nazwa ?? 'brak');
nullish.js
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);
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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].

for-of.js
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));
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

Skrócone zapisy obiektów

ES6 skrócił trzy często powtarzane wzory w literale obiektu:

ZapisPrzed ES6ES6+
właściwość ze zmiennej o tej samej nazwie{ imie: imie, wiek: wiek }{ imie, wiek }
metoda{ przedstaw: function () { … } }{ przedstaw() { … } }
klucz obliczany z wyrażeniaobj[klucz] = w; po utworzeniu{ [klucz]: w }
skrocone.js
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));
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

Ściąga

SkładniaCo robiPrzykł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 undefinedf(5) → y === 10
const [a, b] = tabdestrukturyzacja tablicy (po kolejności)const [rok, mies] = '2026-10'.split('-')
const [a, , c] = tabpominięcie elementuconst [, drugi] = ['x', 'y']
const { p, q = 1 } = objdestrukturyzacja obiektu (po nazwie) z domyślnąconst { imie, wiek = 0 } = uczen
const { p: nowa } = objzmiana nazwy zmiennejconst { imie: pierwsze } = uczen
f({ a, b })destrukturyzacja w parametrzefunction f({ film, ulga = false }) {}
[...a, ...b], { ...o, x: 1 }spread: kopia/łączenie/nadpisanieconst ustaw = { ...domyslne, ...moje }
Math.max(...tab)spread: tablica → argumentyMath.min(...ceny)
function f(...args)rest: argumenty → tablica (ostatni)suma(1, 2, 3) → args = [1, 2, 3]
const [x, ...reszta] = tabrest w destrukturyzacji[1, 2, 3] → x = 1, reszta = [2, 3]
obj?.p, obj?.[k], f?.()undefined zamiast błędu, gdy po lewej null/undefineddane.adres?.miasto
a ?? bb tylko, gdy a jest null/undefinedilosc ?? 1 (zostawia 0)
a || bb, gdy a fałszywe (też 0, "")uwagi || '(brak)'
x ??= wprzypisz, jeśli x jest null/undefinedcfg.host ??= 'localhost'
for (const x of tab)pętla po wartościach iterowalnegofor (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 obiektbez nawiasów zwróci undefined

Zadania

Zadanie 1
łatwe

Karta ucznia

Masz obiekt:

JavaScript
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
karta-ucznia.js
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}`);
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik
Zadanie 2
średnie

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
statystyki.js
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));
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik
Zadanie 3
średnie

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
raty-es6.js
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' }));
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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 }).

Zadanie 4
średnie

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):

JavaScript
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
scal-ustawienia.js
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ęty
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

Spread ...uzytkownika.powiadomienia z wartością undefined (gdy użytkownik nie zapisał powiadomień) jest bezpieczny – spread undefined w literale obiektu po prostu nic nie dodaje.

Zadanie 5
trudne

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:

JavaScript
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
podsumuj.js
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));
Konsola
Kliknij „Uruchom”, aby zobaczyć wynik

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ź.

0/0poprawnych
Sprawdź się

Co wypisze ten kod?

const [a, , c = 10] = [1, 2];
console.log(a, c);
Sprawdź się

Które wyrażenie zwróci 0, gdy const x = 0?

Sprawdź się

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);
Sprawdź się

Który nagłówek funkcji jest poprawny?

Sprawdź się

Co wypisze ten kod?

const dane = { uczen: null };
console.log(dane.uczen?.imie, dane.klasa?.nazwa);
Sprawdź się

Co zwróci wywołanie f()?

const f = () => { nazwa: 'Ala' };
Sprawdź się

Co wypisze ten kod?

function cena(netto, vat = 23) {
return netto + netto * vat / 100;
}
console.log(cena(100, null), cena(100, undefined));
Sprawdź się

Co wypisze ten kod?

const cennik = { kawa: 12, herbata: 9 };
for (const [nazwa, cena] of Object.entries(cennik)) {
console.log(nazwa + ':' + cena);
}
Sprawdź się

Które wywołanie poprawnie przekaże elementy tablicy t = [3, 9, 1] jako osobne argumenty do Math.max?

Sprawdź się

Co wypisze ten kod?

const klucz = 'poziom';
const n = 2;
const obj = { [klucz]: 'trudny', [`etap${n}`]: true };
console.log(Object.keys(obj));