JavaScript w kwalifikacji INF.03: najważniejsze zasady, przykłady i 153 powiązane pytania w banku.
JavaScript w zadaniach INF.03 rzadko występuje jako duży program. Częściej dostajesz kilkanaście linii i pytanie, co znajdzie się w zmiennej albo co pojawi się na ekranie. Punkt zdobywasz, gdy wykonasz ten kod w głowie linia po linii, razem z konwersjami typów i wartością zwracaną przez funkcję. Dlatego każdy przykład poniżej ma podany wynik.
let, const i var: zasięg oraz przypisanie
var ma zasięg całej funkcji, a let i const zasięg bloku, czyli najbliższych klamer. Najwyraźniej widać to na liczniku pętli:
for (var i = 0; i < 3; i++) {}
console.log(i);
// 3 - licznik zyje dalej, bo var nie widzi klamer
for (let j = 0; j < 3; j++) {}
console.log(j);
// ReferenceError - licznik zniknal razem z blokiem
const blokuje ponowne przypisanie, ale nie zawartość tablicy ani obiektu:
const lista = [1, 2];
lista.push(3);
// dziala, lista to teraz [1, 2, 3]
lista = [];
// TypeError - zmieniasz sama zmienna, a nie jej zawartosc
Osobno działa moment odczytu. Zmienna z var odczytana przed deklaracją daje undefined, a let i const w tym samym miejscu rzucają ReferenceError, bo do linii z deklaracją siedzą w martwej strefie.
Konwersje typów i porównanie == kontra ===
Operator + przy tekście łączy i liczy od lewej do prawej; minus, gwiazdka i ukośnik wymuszają liczbę.
Number("12,5")
NaN (separator to kropka)
== porównuje po konwersji, === porównuje wartość i typ:
Do sprawdzania NaN służy Number.isNaN(x), bo globalne isNaN("abc") zwraca true nawet dla tekstu.
Funkcje, funkcje strzałkowe i wartość zwracana
Te dwa zapisy dają dla suma(2, 3) ten sam wynik 5:
function suma(a, b) {
return a + b;
}
const suma = (a, b) => a + b;
Różnica zaczyna się przy klamrach. Strzałka bez klamer zwraca wyrażenie sama, z klamrami trzeba dopisać return:
const zle = (a, b) => { a + b; };
// zwraca undefined - jest obliczenie, nie ma zwrotu
const dobrze = (a, b) => { return a + b; };
const obiekt = (x) => ({ v: x });
// obiekt ze strzalki wymaga nawiasow, inaczej klamra to blok kodu
Deklarację function można wywołać przed jej zapisem; funkcję przypisaną do const w tej samej sytuacji zatrzyma ReferenceError. Brakujący argument daje NaN, bo suma(2) liczy 2 + undefined. Nazwa funkcji bez nawiasów to funkcja jako wartość, z nawiasami to natychmiastowe wywołanie.
Tablice: push, length, indexOf i pętle
Indeksy zaczynają się od zera, więc ostatni element ma indeks o jeden mniejszy niż długość tablicy:
const tab = [10, 20, 30];
tab[tab.length - 1]; // 30, ostatni element
tab[tab.length]; // undefined, poza tablica
tab.push(40); // zwraca 4, czyli NOWA dlugosc
indexOf porównuje tak jak ===, więc typ szukanej wartości ma znaczenie:
[1, 2, 3].indexOf("2"); // -1, bo tekst "2" to nie liczba 2
[1, 2, 3].includes("2"); // false, z tego samego powodu
Trzy pętle po tej samej tablicy dają do ręki trzy różne rzeczy:
for (let i = 0; i < tab.length; i++) { } // i to INDEKS: 0, 1, 2
for (const el of tab) { } // el to WARTOSC: 10, 20, 30
for (const k in tab) { } // k to KLUCZ jako tekst: "0", "1", "2"
Warunek i <= tab.length wykona jeden obieg za dużo i odczyta undefined: częsta pułapka w arkuszu. Przy for..in klucz jest tekstem, więc k + 1 dałoby "01" zamiast 1.
Warunki, wartości fałszywe i pułapki w czytaniu kodu
Fałszywe jest dokładnie sześć wartości: false, 0, "", null, undefined, NaN. Każda inna jest prawdziwa, w tym "0", pusta tablica i " ". Osobno: [] == false daje true, bo pusta tablica zamienia się najpierw na pusty tekst, a potem na zero.
Dwa zapisy, które w arkuszu wyglądają niewinnie i zmieniają wynik:
if (x = 5) {
// POJEDYNCZE "=" przypisuje, wiec warunek jest zawsze prawdziwy
}
switch (wartosc) {
case 1:
// switch dopasowuje przez "===", wiec tekst "1" tu NIE wejdzie
komunikat = "jeden";
case 2:
// brak "break" wyzej: wykonanie leci dalej i nadpisuje komunikat
komunikat = "dwa";
}
Czytając zadanie, zapisuj wartości zmiennych po każdej linii: pamięciowe śledzenie kodu to główne źródło błędów.
DOM, addEventListener i walidacja formularza
Element ze strony pobierasz na dwa sposoby i różnią się tym, co przyjmują:
document.getElementById("wiek");
// samo id, BEZ krzyzyka
document.querySelector("#wiek");
// selektor CSS; zwraca pierwszy pasujacy element albo null
Z pola input czytasz .value, z akapitu .textContent. Wartość .value jest zawsze tekstem, więc dodanie dwóch pól skleja napisy zamiast dodać liczby:
pole1.value + pole2.value;
// "2" + "3" daje "23"
Number(pole1.value) + Number(pole2.value);
// 5
Obsługę zdarzenia podpinasz nazwą funkcji, bez nawiasów:
przycisk.addEventListener("click", sprawdz);
formularz.addEventListener("submit", function (event) {
event.preventDefault();
if (pole.value.trim() === "") {
komunikat.textContent = "Pole nie może być puste";
}
});
Z nawiasami (sprawdz()) wywołasz funkcję od razu przy wczytaniu strony, a pod zdarzenie trafi jej wynik. Bez preventDefault() strona przeładuje się przed pokazaniem komunikatu. Sam if (pole.value) nie wystarcza, bo " " jest prawdziwe: dlatego w przykładzie stoi .trim() === "". Skąd biorą się pola formularza, opisuje artykuł o formularzach, a pełne zadania znajdziesz w arkuszach INF.03.