Temat 04 · 2 × 45 minINF.03
Napisy (String)
Wynik zadania egzaminacyjnego to prawie zawsze napis: „Koszt całkowity: 8000 zł”, „Liczba potrzebnych puszek: 10”, imię i nazwisko WIELKIMI LITERAMI, nazwa pliku wycięta ze ścieżki. Egzaminator porównuje ten tekst z arkuszem co do dwukropka. W tej lekcji nauczysz się budować napisy ze zmiennych (dwoma sposobami), wycinać z nich fragmenty, szukać w nich znaków i zamieniać wielkość liter – czyli wszystkiego, co sprawdza część pisemna i co wypisuje część praktyczna.
Jak zapisać napis
Napis (ang. string) to ciąg znaków w cudzysłowach. JavaScript dopuszcza trzy rodzaje:
const a = "Cudzysłów podwójny";
const b = 'Apostrof – to samo';
const c = `Odwrotny apostrof – szablon (template string)`;
console.log(a);
console.log(b);
console.log(c);Pierwsze dwa są równoważne – wybierz jeden styl i trzymaj się go (w tym kursie: "…"). Trzeci ma dodatkowe możliwości, które poznasz za chwilę. Cudzysłów innego rodzaju może stać wewnątrz napisu bez problemu; ten sam trzeba poprzedzić ukośnikiem \:
console.log('Powiedział: "Cześć"'); // apostrofy na zewnątrz, cudzysłowy w środku
console.log("Powiedział: \"Cześć\""); // albo ukośnik przed cudzysłowem
console.log("Nowa\nlinia"); // \n = znak nowej linii
console.log("Tabulator\tmiędzy słowami"); // \t = tabulator
console.log("C:\\fakepath\\plik.png"); // \\ = jeden ukośnik wsteczny
console.log(""); // pusty napis – ma 0 znaków, ale istniejeSklejanie: + i szablon
Tekst wyniku zawsze składa się z fragmentów stałych i wartości ze zmiennych. Pierwszy sposób to operator + (konkatenacja), który znasz z poprzedniej lekcji:
const miasto = "Warszawa";
const koszt = 8000;
const raty = 10;
const rata = koszt / raty;
console.log("Kurs odbędzie się w " + miasto + ". Koszt całkowity: " + koszt + " zł. Płacisz " + raty + " rat po " + rata + " zł");Działa, ale łatwo zgubić spację albo cudzysłów. Drugi sposób – szablon (template string) w odwrotnych apostrofach – pozwala wstawiać wartości bezpośrednio w tekst przez ${…}:
const miasto = "Warszawa";
const koszt = 8000;
const raty = 10;
console.log(`Kurs odbędzie się w ${miasto}. Koszt całkowity: ${koszt} zł. Płacisz ${raty} rat po ${koszt / raty} zł`);W ${…} może stać dowolne wyrażenie: zmienna, działanie, wywołanie metody (${cena.toFixed(2)}). Szablon może też zajmować kilka linii – znaki nowej linii zostają w napisie.
Co wypisze ten kod?
const sztuk = 3;
const cena = 4;
console.log(`Razem: ${sztuk * cena} zł`);
console.log("Razem: " + sztuk * cena + " zł");
console.log("Razem: " + sztuk + cena + " zł");Szablon ma jedną ogromną zaletę przy obliczeniach: ${sztuk + cena} zawsze doda liczby, bo w klamrach wyrażenie jest liczone najpierw, a dopiero wynik wstawiany w tekst. Przy + musisz pilnować nawiasów: "Razem: " + (sztuk + cena).
Długość i pojedyncze znaki
Właściwość length (bez nawiasów!) zwraca liczbę znaków. Znaki numerujesz od 0: pierwszy znak ma indeks 0, ostatni length - 1.
Co wypisze ten kod?
const slowo = "Egzamin";
console.log(slowo.length, slowo[0], slowo[6], slowo[7]);const slowo = "Egzamin";
console.log(slowo.length); // 7
console.log(slowo[0]); // "E" – pierwszy znak
console.log(slowo[slowo.length - 1]); // "n" – ostatni znak
console.log(slowo.at(-1)); // "n" – to samo, krócej (at z ujemnym indeksem)
console.log(slowo.charAt(2)); // "z" – starszy zapis, równoważny slowo[2]
console.log(slowo[20]); // undefined – poza napisem
console.log("".length); // 0Napisy są niezmienne: nie da się podmienić jednej litery przez slowo[0] = "X" (przeglądarka po cichu zignoruje to przypisanie). Każda metoda z tej lekcji zwraca nowy napis, a oryginał zostaje bez zmian – dlatego wynik zawsze trzeba zapisać do zmiennej.
const imie = "ola";
imie.toUpperCase(); // zwraca "OLA", ale nic z tym nie robimy…
console.log(imie); // …więc imie nadal "ola"
const duze = imie.toUpperCase(); // trzeba zapisać wynik
console.log(duze);Wielkość liter
toUpperCase() zwraca napis WIELKIMI literami, toLowerCase() – małymi. Polskie znaki działają poprawnie. Dwa zastosowania egzaminacyjne: wypisanie imienia i nazwiska wielkimi literami (styczeń 2024, INF.03-01-24.01) oraz porównywanie bez względu na wielkość liter – sprowadzasz oba napisy do małych liter, a potem porównujesz.
Co zostanie wyświetlone po wykonaniu kodu?
word = "Słoń";
document.write(word.toLowerCase() == 'słoń');const word = "Słoń";
console.log(word.toLowerCase()); // słoń
console.log(word.toUpperCase()); // SŁOŃ
console.log(word.toLowerCase() == "słoń"); // true – wynik porównania, nie napis
console.log(word == "słoń"); // false – wielkość liter ma znaczenie
console.log("Jan Kowalski".toUpperCase()); // JAN KOWALSKIWycinanie fragmentu: slice
slice(start, koniec) zwraca fragment od indeksu start do indeksu koniec wyłącznie (znak o indeksie koniec już nie wchodzi). Długość wyniku to zawsze koniec - start. Drugi argument można pominąć – wtedy do końca napisu. Ujemne indeksy liczą od końca.
Co będzie zawierała zmienna str2?
var str1 = "JavaScript";
var str2 = str1.slice(2, 6);const tekst = "JavaScript";
console.log(tekst.slice(2, 6)); // "vaSc" – indeksy 2–5
console.log(tekst.slice(4)); // "Script" – od 4 do końca
console.log(tekst.slice(-6)); // "Script" – ostatnie 6 znaków
console.log(tekst.slice(0, 4)); // "Java" – pierwsze 4 znaki
console.log(tekst.substring(2, 6)); // "vaSc" – starsza metoda, podobnaRóżnica slice / substring: substring nie rozumie ujemnych indeksów i zamienia argumenty, jeśli podasz je w odwrotnej kolejności. Istnieje jeszcze substr(start, długość) – jest przestarzała, ale działa i możesz ją spotkać w starych pytaniach. Sam używaj slice.
Szukanie w napisie
| Metoda | Zwraca | Przykład dla "banan" |
|---|---|---|
indexOf(szukane) | indeks pierwszego wystąpienia lub -1 | .indexOf("an") → 1 |
lastIndexOf(szukane) | indeks ostatniego wystąpienia lub -1 | .lastIndexOf("an") → 3 |
includes(szukane) | true / false – czy zawiera | .includes("nan") → true |
startsWith(szukane) | czy zaczyna się od | .startsWith("ba") → true |
endsWith(szukane) | czy kończy się na | .endsWith(".png") → false |
const owoc = "banan";
console.log(owoc.indexOf("an"), owoc.lastIndexOf("an")); // 1 3
console.log(owoc.indexOf("x")); // -1 – nie znaleziono
console.log(owoc.includes("nan"), owoc.includes("NAN")); // true false – wielkość liter!
console.log("zdjecie.png".endsWith(".png")); // true
console.log("Ala ma kota".indexOf(" ")); // 3 – pozycja pierwszej spacjiWszystkie te metody rozróżniają wielkość liter. Gdy ma nie mieć znaczenia, połącz je z toLowerCase(): tekst.toLowerCase().includes("kot").
Która metoda sprawdzi, czy napis email zawiera znak @, zwracając true albo false?
Nazwa pliku ze ścieżki – zadanie z 2026 roku
Pole <input type="file"> zwraca w value napis C:\fakepath\zdjecie.png – przeglądarka ukrywa prawdziwy folder. Arkusz ze stycznia 2026 wymagał „nazwy pliku bez ścieżki dostępu”. Schemat: znajdź ostatni ukośnik wsteczny i wytnij wszystko za nim.
const sciezka = "C:\\fakepath\\zdjecie.png"; // w kodzie: podwójne ukośniki
console.log(sciezka); // C:\fakepath\zdjecie.png
const pozycja = sciezka.lastIndexOf("\\"); // indeks ostatniego ukośnika: 11
const nazwaPliku = sciezka.slice(pozycja + 1); // od znaku za ukośnikiem do końca
console.log(nazwaPliku); // zdjecie.pnglastIndexOf, nie indexOf – pierwszy ukośnik stoi po C:. Plus 1, bo slice(pozycja) zaczęłoby od samego ukośnika. Ten sam wynik daje sciezka.split("\\").pop() – poznasz to przy tablicach.
Zamiana i czyszczenie
| Metoda | Co robi | Przykład |
|---|---|---|
replace(co, naCo) | zamienia pierwsze wystąpienie | "3,5 kg".replace(",", ".") → "3.5 kg" |
replaceAll(co, naCo) | zamienia wszystkie wystąpienia | "a-b-c".replaceAll("-", " ") → "a b c" |
trim() | usuwa spacje z początku i końca | " Ola ".trim() → "Ola" |
padStart(dl, znak) | dopełnia z przodu do długości dl | "7".padStart(2, "0") → "07" |
repeat(n) | powtarza napis n razy | "ab".repeat(3) → "ababab" |
console.log("ala ma kota".replace("a", "o")); // "ola ma kota" – tylko pierwsze a
console.log("ala ma kota".replaceAll("a", "o")); // "olo mo koto"
console.log(" Jan ".trim() + "|"); // "Jan|"
console.log(" Jan ".length, " Jan ".trim().length); // 7 3
console.log("5".padStart(2, "0") + ":" + "9".padStart(2, "0")); // "05:09"
console.log(parseFloat("3,5".replace(",", "."))); // 3.5 – przecinek z pola tekstowegotrim() przydaje się przy walidacji: użytkownik, który wpisał same spacje, nie podał danych – pole.value.trim() === "" to wykrywa, a pole.value === "" nie.
Dzielenie napisu: split
split(separator) zamienia napis na tablicę – listę fragmentów rozdzielonych separatorem. Tablice poznasz dokładnie w lekcji Tablice; tu wystarczy wiedzieć, że do elementów sięgasz indeksem [0], [1]…
Która metoda napisu zwraca tablicę jego fragmentów?
const osoba = "Jan Kowalski";
const czesci = osoba.split(" "); // tablica: ["Jan", "Kowalski"]
console.log(czesci);
console.log(czesci[0], czesci[1]); // Jan Kowalski
console.log(czesci.length); // 2 – liczba elementów
const data = "2026-10-20".split("-");
console.log(data[0], data[1], data[2]); // 2026 10 20
console.log("kot".split("")); // ["k", "o", "t"] – pusty separator = osobne znakiPorównywanie napisów
Napisy porównujesz === (identyczne) albo <, > (porządek alfabetyczny według kodów znaków). Dwie pułapki:
console.log("Ala" === "ala"); // false – wielkość liter
console.log("Ala".toLowerCase() === "ala".toLowerCase()); // true
console.log("10" < "9"); // true! – porównanie napisów idzie znak po znaku: "1" < "9"
console.log(10 < 9); // false – liczby porównują się normalnie
console.log("B" < "a"); // true – wielkie litery mają niższe kody niż małeWniosek dla zadań z formularzem: jeśli porównujesz wartości liczbowe, najpierw je skonwertuj (parseFloat), inaczej "100" < "20" da true. Więcej o porównaniach w lekcji Porównania i instrukcje warunkowe.
Na egzaminie
Ściąga
| Składnia | Co robi | Przykład → wynik |
|---|---|---|
"…", '…' | napis | "Ola" |
`Tekst ${wyrażenie}` | szablon – wstawia wartość | `Koszt: ${2 * 5} zł` → "Koszt: 10 zł" |
a + b | sklejenie napisów | "Ala" + " " + "Nowak" |
\n, \", \\ | nowa linia, cudzysłów, ukośnik | "C:\\plik" → C:\plik |
s.length | liczba znaków (bez nawiasów) | "Egzamin".length → 7 |
s[i], s.at(-1) | znak o indeksie i (od 0), ostatni znak | "Egzamin"[0] → "E" |
s.toUpperCase(), s.toLowerCase() | wielkie / małe litery | "Słoń".toLowerCase() → "słoń" |
s.slice(a, b) | fragment od a do b wyłącznie; ujemne od końca | "JavaScript".slice(2, 6) → "vaSc" |
s.indexOf(x) | pozycja pierwszego x lub -1 | "banan".indexOf("an") → 1 |
s.lastIndexOf(x) | pozycja ostatniego x lub -1 | "banan".lastIndexOf("an") → 3 |
s.includes(x) | czy zawiera – true/false | "banan".includes("nan") → true |
s.startsWith(x), s.endsWith(x) | czy zaczyna / kończy się na | "a.png".endsWith(".png") → true |
s.replace(a, b) | zamienia pierwsze a na b | "3,5".replace(",", ".") → "3.5" |
s.replaceAll(a, b) | zamienia wszystkie | "a-b-c".replaceAll("-", "") → "abc" |
s.trim() | usuwa spacje z brzegów | " x ".trim() → "x" |
s.padStart(n, z) | dopełnia z przodu do n znaków | "7".padStart(2, "0") → "07" |
s.split(sep) | napis → tablica fragmentów | "a,b".split(",") → ["a", "b"] |
| nazwa pliku ze ścieżki | ostatni \ + 1 | s.slice(s.lastIndexOf("\\") + 1) |
Zadania
Wizytówka
Dla zmiennych imie = "anna" i nazwisko = "kowalska" wypisz w konsoli trzy linie: imię i nazwisko z wielkich liter na początku (Anna Kowalska), inicjały (A.K.) oraz zdanie Imię ma 4 litery, nazwisko 8. Użyj slice, toUpperCase, length i szablonu.
Pokaż rozwiązanie
const imie = "anna";
const nazwisko = "kowalska";
// pierwsza litera wielka + reszta bez zmian
const imieLadne = imie[0].toUpperCase() + imie.slice(1);
const nazwiskoLadne = nazwisko[0].toUpperCase() + nazwisko.slice(1);
console.log(`${imieLadne} ${nazwiskoLadne}`);
const inicjaly = `${imie[0].toUpperCase()}.${nazwisko[0].toUpperCase()}.`;
console.log(inicjaly);
console.log(`Imię ma ${imie.length} litery, nazwisko ${nazwisko.length}.`);Domena z adresu e-mail
Dla adresu " Jan.Kowalski@Szkola.EDU.pl " (ze spacjami, jak wpisany w pole) wypisz: czyszczony adres małymi literami, część przed @ (login), część po @ (domenę) oraz informację Adres zawiera @: true. Sprawdź też drugi adres bez @ – "jan.kowalski.pl" – login i domena powinny wtedy być puste albo wynik powinien jasno pokazać brak znaku.
Pokaż rozwiązanie
const wpisany = " Jan.Kowalski@Szkola.EDU.pl ";
const email = wpisany.trim().toLowerCase(); // czyścimy raz, na początku
console.log(email); // jan.kowalski@szkola.edu.pl
const pozycjaMalpy = email.indexOf("@"); // 12
console.log("Adres zawiera @:", email.includes("@"));
console.log("Login:", email.slice(0, pozycjaMalpy)); // do @ wyłącznie
console.log("Domena:", email.slice(pozycjaMalpy + 1)); // za @ do końca
// Drugi adres – bez małpy indexOf zwraca -1
const zly = "jan.kowalski.pl";
console.log("Adres zawiera @:", zly.includes("@")); // false
console.log("Pozycja @:", zly.indexOf("@")); // -1 – sygnał, że nie ma czego wycinaćUwaga na drugi przypadek: zly.slice(0, -1) wycięłoby cały napis bez ostatniej litery, a nie „nic” – dlatego przed wycinaniem trzeba sprawdzić, czy indexOf nie zwrócił -1. Zrobisz to instrukcją if w następnej lekcji.
Komunikat kalkulatora rat
Fragment zadania w stylu arkusza ze stycznia 2025 (INF.03-01-25.01). Skrypt ma wypisać w konsoli tekst dokładnie w postaci:
Kurs odbędzie się w <miasto>. Koszt całkowity: <kwota> zł. Płacisz <liczba> rat po <rata> zł
Dane: wybrane kursy – React.js (5000 zł) i JavaScript (3000 zł), oba wybrane; liczba rat jako napis z pola "10"; miasto "Katowice". Rata to koszt podzielony przez liczbę rat. Przetestuj na drugim zestawie: tylko kurs JavaScript, "12" rat, "Gdańsk" – rata ma mieć co najwyżej 2 miejsca po przecinku.
Kryteria oceny (zero-jedynkowe, wzorowane na zasadach oceniania tej sesji):
- Skrypt w języku JavaScript, co najmniej jedna poprawna składniowo instrukcja.
- Liczba rat jest konwertowana na liczbę przed dzieleniem.
- Koszt całkowity to suma cen wybranych kursów.
- Rata to koszt całkowity podzielony przez liczbę rat.
- Tekst wyniku zawiera miasto – sprawdzane dla dwóch różnych miast.
- Tekst zawiera koszt całkowity oraz liczbę rat i ratę – sprawdzane dla dwóch zestawów wartości.
- Tekst ma dokładnie podaną postać (kropki, dwukropek, „zł”).
- Znaczące nazwy zmiennych.
Pokaż rozwiązanie
// Zestaw 1
const cenaReact = 5000;
const cenaJavaScript = 3000;
const liczbaRat = parseInt("10"); // kryterium 2 – z pola przychodzi napis
const miasto = "Katowice";
const kosztCalkowity = cenaReact + cenaJavaScript; // kryterium 3 (oba kursy wybrane)
const rata = kosztCalkowity / liczbaRat; // kryterium 4
console.log(`Kurs odbędzie się w ${miasto}. Koszt całkowity: ${kosztCalkowity} zł. Płacisz ${liczbaRat} rat po ${rata} zł`);
// Zestaw 2 – tylko JavaScript, 12 rat, Gdańsk
const liczbaRat2 = parseInt("12");
const miasto2 = "Gdańsk";
const kosztCalkowity2 = cenaJavaScript;
const rata2 = kosztCalkowity2 / liczbaRat2; // 250
console.log(`Kurs odbędzie się w ${miasto2}. Koszt całkowity: ${kosztCalkowity2} zł. Płacisz ${liczbaRat2} rat po ${rata2.toFixed(2)} zł`);W prawdziwym zadaniu wybór kursów przyjdzie z checkboxów, a sumowanie „tylko zaznaczonych” zrobisz instrukcją if (lekcje Warunki i Wzorzec „kalkulator”). Szablon ${a + b} chroni przed sklejeniem liczb z tekstem stojącym przed nimi (jak w "Razem: " + a + b), ale nie przed "5000" + "3000" – wartości z pól trzeba najpierw zamienić na liczby.
Nazwa pliku bez ścieżki
Fragment zadania w stylu arkusza ze stycznia 2026. Z wartości pola type="file" – na razie symulowanej napisem – ustal nazwę pliku bez ścieżki i wypisz komunikat Wzór: <plik>, kolor <kolor> w cenie <cena> zł. Dane: ścieżka C:\fakepath\smok.png, kolor "Czarny", cena z pola "250". Sprawdź dla drugiej ścieżki C:\fakepath\roza-wiatrow.jpg i upewnij się, że rozwiązanie nie zakłada stałej długości nazwy.
Kryteria oceny:
- Nazwa pliku jest ustalana z wartości ścieżki, bez katalogów – sprawdzane dla dwóch różnych nazw.
- Komunikat zawiera nazwę pliku, kolor i cenę w podanym formacie.
- Cena jest konwertowana na liczbę (w pełnym zadaniu bierze udział w obliczeniach).
- Znaczące nazwy zmiennych.
Pokaż rozwiązanie
// W kodzie ukośniki wsteczne podwajamy; z pola file przyjdą pojedyncze
const sciezka = "C:\\fakepath\\smok.png";
const kolor = "Czarny";
const cena = parseFloat("250"); // kryterium 3
const nazwaPliku = sciezka.slice(sciezka.lastIndexOf("\\") + 1); // kryterium 1
console.log(`Wzór: ${nazwaPliku}, kolor ${kolor} w cenie ${cena} zł`);
// Drugi zestaw – inna długość nazwy, ten sam kod
const sciezka2 = "C:\\fakepath\\roza-wiatrow.jpg";
const nazwaPliku2 = sciezka2.slice(sciezka2.lastIndexOf("\\") + 1);
console.log(`Wzór: ${nazwaPliku2}, kolor Zielony w cenie ${cena} zł`);Rozwiązanie sciezka.slice(12) zadziałałoby dla C:\fakepath\, bo ten przedrostek ma zawsze 12 znaków – ale egzaminator nie musi testować w tej samej przeglądarce i systemie, więc lastIndexOf jest bezpieczniejsze i pokazuje, że rozumiesz zadanie.
Formularz kontaktowy – komunikat
Zadanie w stylu arkusza ze stycznia 2024 (INF.03-01-24.01). Z pól przychodzą napisy (ze zbędnymi spacjami): imię " ola ", nazwisko " nowak", zgłoszenie "Nie działa logowanie do panelu. ". Zbuduj jeden napis komunikatu, który:
- w pierwszej linii zawiera imię i nazwisko wielkimi literami, rozdzielone jedną spacją, bez zbędnych spacji,
- w drugiej linii zawiera tekst
Treść Twojej sprawy:, - w trzeciej linii zawiera treść zgłoszenia bez spacji na brzegach,
- dodatkowo wypisz liczbę znaków zgłoszenia i informację, czy zgłoszenie zawiera słowo „logowanie” (bez względu na wielkość liter).
Wypisz komunikat jednym console.log.
Pokaż rozwiązanie
const imieWpisane = " ola ";
const nazwiskoWpisane = " nowak";
const zgloszenieWpisane = "Nie działa logowanie do panelu. ";
// Najpierw czyścimy, potem przetwarzamy – i zapisujemy wyniki do zmiennych
const imieNazwisko = `${imieWpisane.trim()} ${nazwiskoWpisane.trim()}`.toUpperCase();
const zgloszenie = zgloszenieWpisane.trim();
// Szablon wieloliniowy – znaki nowej linii zostają w napisie
const komunikat = `${imieNazwisko}
Treść Twojej sprawy:
${zgloszenie}`;
console.log(komunikat);
console.log("Liczba znaków zgłoszenia:", zgloszenie.length);
console.log("Dotyczy logowania:", zgloszenie.toLowerCase().includes("logowanie"));Na stronie znak nowej linii w innerHTML nie łamie tekstu – tam użyjesz <br> zamiast \n (lekcja Model DOM). W konsoli \n działa. Zwróć uwagę na kolejność: trim() przed toUpperCase() nie ma znaczenia dla wyniku, ale trim() przed length – ma, bo inaczej policzysz spacje.
Test powtórkowy
Test powtórkowy
Format jak w części pisemnej INF.03: 4 odpowiedzi, 1 poprawna. Kod w dialekcie egzaminacyjnym (var, document.write).
Jaką wartość będzie miała zmienna str2?
var str1 = "Programowanie";
var str2 = str1.slice(3, 7);Aby zamienić napis '2026-10-20' na tablicę trzech elementów, należy użyć metody
Co wyświetli poniższy kod?
var word = "KOT";
document.write(word.toLowerCase() == "kot");Metoda includes() wywołana na napisie
Co wypisze poniższy kod?
var tekst = "Egzamin";
console.log(tekst.length + " " + tekst[1]);Zmienna sciezka ma wartość C:\fakepath\obraz.jpg. Które wyrażenie zwróci samą nazwę pliku obraz.jpg?
Co wypisze poniższy kod?
var cena = 20;
var sztuk = 3;
console.log("Razem: " + cena * sztuk + " zł");
console.log("Razem: " + cena + sztuk + " zł");Które wywołanie zwróci napis JAN KOWALSKI dla zmiennej var osoba = 'jan kowalski';?
Co wypisze console.log('banan'.indexOf('x'))?
Co wypisze poniższy kod?
var imie = "ola";
imie.toUpperCase();
console.log(imie);