Podstawy JavaScriptu od zera - zmienne, DOM i pierwsze projekty

Diagram przedstawiający strukturę dokumentu HTML, od elementu głównego `<html>` po `head` i `body`, z przykładami elementów i tekstu. Podstawy javascriptu można zrozumieć, analizując strukturę DOM.

Napisano przez

Jacek Zając

Opublikowano

19 wrz 2026

Spis treści

Przy pierwszym kontakcie z JavaScriptem łatwo ugrzęznąć w składni i zapomnieć, po co właściwie pisze się ten kod. Podstawy JavaScriptu obejmują nie tylko zmienne i funkcje, lecz także pracę z przeglądarką, reakcję na kliknięcia, zmianę treści strony oraz logiczne myślenie potrzebne w każdym projekcie webowym.

Najważniejsze elementy JavaScriptu tworzą spójną ścieżkę nauki

  • JavaScript dodaje stronom interaktywność i pozwala reagować na działania użytkownika.
  • const i let są dziś podstawą deklarowania zmiennych.
  • Funkcje, warunki i pętle pozwalają opisywać logikę programu.
  • DOM i zdarzenia łączą kod z elementami widocznymi w przeglądarce.
  • Regularne ćwiczenia dają lepsze efekty niż samo oglądanie kursów.

Drzewo DOM: document > html > body. Podstawy javascriptu pokazują, jak kliknięcie przycisku zmienia tekst w h1.

Do czego służy JavaScript i jak działa w przeglądarce

JavaScript to język programowania, który pozwala tworzyć dynamiczne zachowanie stron internetowych. HTML odpowiada za strukturę, CSS za wygląd, a JavaScript za reakcję na działania użytkownika, walidację formularzy, zmianę treści, animacje czy pobieranie danych z serwera.

Sam język jest standaryzowany jako ECMAScript. Przeglądarka dostarcza jednak dodatkowe interfejsy, na przykład DOM, czyli model dokumentu HTML, oraz Web API do obsługi zdarzeń, sieci i pamięci lokalnej. To rozróżnienie jest ważne, bo JavaScript i możliwości przeglądarki nie są dokładnie tym samym.

Najprostszy sposób uruchomienia kodu to dołączenie pliku do dokumentu HTML:

Atrybut defer sprawia, że plik zostanie pobrany bez blokowania odczytywania HTML, a uruchomiony dopiero po zbudowaniu dokumentu. W małych ćwiczeniach można też używać konsoli deweloperskiej w przeglądarce. Ja często polecam ten sposób na samym początku, bo pozwala szybko sprawdzić pojedynczą instrukcję bez tworzenia całego projektu.

Pierwszy działający fragment

const imie = "Ola";
console.log(`Cześć, ${imie}!`);

console.log() wyświetla wartość w konsoli, a zapis z odwrotnymi apostrofami pozwala wstawiać zmienne do tekstu. To drobiazg, ale od razu pokazuje dwie ważne rzeczy: program przechowuje dane i potrafi wykorzystać je w działaniu.

Zmienne, typy danych i operatorzy bez zbędnego zamieszania

Zmienna to nazwana wartość, z której program może korzystać. W nowoczesnym JavaScripcie najczęściej używam const, gdy przypisanie nie będzie zmieniane, oraz let, gdy wartość ma się zmieniać.

const cena = 49.99;
let liczbaSztuk = 1;

liczbaSztuk = 2;

const razem = cena * liczbaSztuk;
console.log(razem);

Nie używaj var w nowych projektach, chyba że świadomie pracujesz ze starszym kodem. const nie oznacza, że obiekt albo tablica staną się całkowicie niezmienne. Blokuje ponowne przypisanie zmiennej, ale zawartość obiektu nadal może zostać zmodyfikowana.

Najczęściej spotykane typy danych to:

  • string, czyli tekst, na przykład "JavaScript",
  • number, czyli liczby całkowite i dziesiętne,
  • boolean, czyli true albo false,
  • undefined, gdy wartości jeszcze nie przypisano,
  • null, gdy celowo oznaczamy brak wartości,
  • object, czyli obiekty i tablice przechowujące bardziej złożone dane.

JavaScript jest językiem dynamicznie typowanym. Oznacza to, że zmienna może w czasie działania programu przechowywać wartości różnych typów. Ta elastyczność przyspiesza prototypowanie, ale bywa też źródłem trudnych do znalezienia błędów, dlatego przy ważnych porównaniach stosuję operator ścisłej równości ===.

const liczba = 5;

console.log(liczba === "5"); // false
console.log(liczba === 5);   // true

Operatory arytmetyczne służą do obliczeń, a operatory logiczne pozwalają łączyć warunki. Początkujący często skupiają się na zapamiętaniu symboli, lecz większą wartość daje przećwiczenie ich na konkretnych zadaniach, takich jak kalkulator ceny, sprawdzanie wieku czy obliczanie wyniku testu.

Warunki, pętle i funkcje budują logikę programu

Instrukcja warunkowa pozwala programowi podjąć decyzję. Dzięki niej kod może wykonać inną operację dla osoby zalogowanej, inną dla gościa albo wyświetlić komunikat zależny od wyniku formularza.

const wynik = 78;

if (wynik >= 50) {
  console.log("Zaliczone");
} else {
  console.log("Spróbuj ponownie");
}

Przy kilku możliwych wartościach przydaje się else if, a przy prostym przypisaniu warunkowym operator trójargumentowy:

const status = wynik >= 50 ? "zaliczone" : "niezaliczone";

Pętle wykorzystuję wtedy, gdy trzeba powtórzyć operację. Pętla for dobrze sprawdza się przy znanej liczbie powtórzeń, a for...of przy przechodzeniu po elementach tablicy.

const technologie = ["HTML", "CSS", "JavaScript"];

for (const technologia of technologie) {
  console.log(technologia);
}

Funkcja grupuje instrukcje wykonujące określone zadanie. Dobrze nazwana funkcja ułatwia czytanie kodu i ogranicza powielanie tych samych fragmentów.

function obliczCeneBrutto(cenaNetto, vat) {
  return cenaNetto * (1 + vat);
}

const cena = obliczCeneBrutto(100, 0.23);
console.log(cena);

Współczesny kod często korzysta także z funkcji strzałkowych:

const pomnóż = (a, b) => a * b;

Nie traktuję funkcji strzałkowych jako celu samego w sobie. Są krótkie i wygodne, ale na początku ważniejsze jest zrozumienie parametrów, wartości zwracanej i zakresu zmiennych. Dopiero później warto zagłębiać się w domknięcia, kontekst this czy programowanie funkcyjne.

Tablice i obiekty w codziennym kodzie

Tablica przechowuje uporządkowany zestaw wartości, a obiekt opisuje rzecz za pomocą właściwości. W praktycznych aplikacjach te dwa typy danych pojawiają się niemal bez przerwy.

const użytkownik = {
  imie: "Ania",
  wiek: 28,
  aktywny: true
};

console.log(użytkownik.imie);

Do pracy z tablicami przydają się metody takie jak map(), filter() i find(). Ich znajomość pozwala pisać krótszy i czytelniejszy kod bez ręcznego zarządzania każdym indeksem.

const ceny = [10, 20, 30];

const zPodatkiem = ceny.map(cena => cena * 1.23);
const drogie = ceny.filter(cena => cena > 15);

console.log(zPodatkiem);
console.log(drogie);

Najczęstszy błąd na tym etapie polega na myleniu map() z forEach(). map() tworzy nową tablicę, natomiast forEach() służy głównie do wykonania działania dla każdego elementu. To małe rozróżnienie szybko zaczyna mieć znaczenie w większych fragmentach aplikacji.

DOM i zdarzenia sprawiają, że strona reaguje

Sam kod uruchomiony w konsoli niewiele zmienia na stronie. Do połączenia JavaScriptu z HTML-em służy DOM, czyli obiektowa reprezentacja dokumentu, po której można wyszukiwać elementy, zmieniać ich treść i reagować na zdarzenia.


const przycisk = document.querySelector("#przycisk");
const komunikat = document.querySelector("#komunikat");

przycisk.addEventListener("click", () => {
  komunikat.textContent = "Przycisk został kliknięty";
});

querySelector() wyszukuje element zgodny z selektorem CSS, a addEventListener() podpina funkcję wykonywaną po wystąpieniu zdarzenia. W tym przypadku jest nim kliknięcie, ale podobnie obsługuje się między innymi wpisywanie w pole tekstowe, wysłanie formularza czy najechanie kursorem.

Walidacja formularza jako dobre ćwiczenie

const formularz = document.querySelector("#formularz");
const email = document.querySelector("#email");
const blad = document.querySelector("#blad");

formularz.addEventListener("submit", (zdarzenie) => {
  zdarzenie.preventDefault();

  if (!email.value.includes("@")) {
    blad.textContent = "Podaj poprawny adres e-mail.";
    return;
  }

  blad.textContent = "Formularz jest poprawny.";
});

To ćwiczenie pokazuje kilka fundamentów naraz: wybieranie elementów, zdarzenia, warunek, pracę z właściwością value i zatrzymanie domyślnego działania formularza. Trzeba jednak pamiętać, że walidacja w przeglądarce nie zastępuje walidacji na serwerze. Użytkownik może zmienić kod strony albo wysłać żądanie niezależnie od interfejsu.

Asynchroniczność i dane z serwera pojawiają się szybciej, niż się wydaje

Współczesna strona często pobiera dane bez pełnego przeładowania dokumentu. Służy do tego między innymi fetch(), który zwraca obietnicę, czyli obiekt reprezentujący wynik operacji dostępny dopiero po pewnym czasie.

async function pobierzDane() {
  try {
    const odpowiedz = await fetch("/api/produkty");

    if (!odpowiedz.ok) {
      throw new Error("Nie udało się pobrać danych");
    }

    const produkty = await odpowiedz.json();
    console.log(produkty);
  } catch (blad) {
    console.error(blad.message);
  }
}

pobierzDane();

Słowo kluczowe async oznacza funkcję asynchroniczną, a await pozwala poczekać na wynik bez blokowania całej aplikacji. Blok try...catch obsługuje błędy, na przykład brak sieci albo odpowiedź serwera z kodem błędu.

Nie zaczynałbym nauki od skomplikowanych aplikacji pobierających dane z wielu źródeł. Najpierw dobrze działa prosty projekt lokalny, potem jeden request i dopiero później obsługa ładowania, pustych wyników oraz błędów. Asynchroniczność jest łatwiejsza, gdy rozumiesz wcześniej funkcje, warunki i obiekty.

Jak ćwiczyć, żeby naprawdę robić postępy

Najskuteczniejsza ścieżka nauki nie polega na zapamiętaniu całej składni. Lepiej opanować niewielki zestaw konstrukcji i używać ich w kilku małych projektach, aż przestaną wymagać ciągłego sprawdzania dokumentacji.

  1. Zbuduj prosty kalkulator korzystający ze zmiennych, operatorów i funkcji.
  2. Dodaj listę zadań, aby przećwiczyć tablice, obiekty i DOM.
  3. Stwórz formularz z walidacją oraz komunikatami dla użytkownika.
  4. Pobierz dane z publicznego endpointu i wyświetl je na stronie.
  5. Dodaj obsługę błędów, stan ładowania i możliwość ponowienia operacji.

Każdy projekt powinien mieć zakres, który da się zamknąć w kilka godzin. To ważniejsze, niż brzmi. Zbyt duża aplikacja szybko zamienia naukę w walkę z konfiguracją i cudzym kodem, a początkujący nie wie już, czy problem dotyczy JavaScriptu, HTML-a, CSS-u czy narzędzia budującego projekt.

Przeczytaj również: JS match() – Jak poprawnie dopasować tekst? Poradnik

Jak rozwiązywać błędy

Gdy program nie działa, nie zgaduj przez kilkanaście minut. Odczytaj komunikat w konsoli, sprawdź linię wskazaną przez przeglądarkę i dodaj tymczasowe console.log() w miejscach, gdzie wartość może być inna, niż zakładasz.

  • SyntaxError zwykle oznacza błąd składni, na przykład brak nawiasu.
  • ReferenceError pojawia się, gdy kod odwołuje się do nieistniejącej zmiennej.
  • TypeError często oznacza próbę wykonania operacji na wartości nieodpowiedniego typu.
  • Brak reakcji przy kliknięciu może wynikać z błędnego selektora albo uruchomienia skryptu przed zbudowaniem DOM-u.

W praktyce największą różnicę robi umiejętność zawężania problemu. Zamiast przepisywać cały fragment, sprawdzam kolejno, czy element istnieje, czy zdarzenie zostało podpięte, czy funkcja się uruchamia i czy otrzymuje właściwe dane. Debugowanie to część programowania, a nie dowód porażki.

Małe projekty najlepiej utrwalają podstawy JavaScriptu

Po opanowaniu zmiennych, warunków, funkcji, tablic, DOM-u i zdarzeń można zacząć budować własne miniaplikacje. Dobrym sprawdzianem będzie lista zadań z filtrowaniem, quiz z liczeniem punktów albo galeria reagująca na wybór zdjęcia.

Nie ma potrzeby od razu przechodzić do Reacta, Vue czy innego frameworka. Narzędzia tego typu są przydatne przy większych interfejsach, ale nie zastąpią rozumienia języka. Jeśli nie wiesz, czym jest funkcja, tablica, zdarzenie albo zakres zmiennej, framework tylko przykryje problem kolejną warstwą abstrakcji.

Najlepszy następny krok to wybrać jeden mały projekt, opisać jego funkcje na kartce i wdrażać je pojedynczo. Po kilku takich ćwiczeniach składnia zaczyna schodzić na drugi plan, a najważniejsza staje się umiejętność rozbicia problemu na mniejsze, sprawdzalne działania.

FAQ - Najczęstsze pytania

Na początku warto uruchamiać pojedyncze instrukcje w konsoli deweloperskiej albo dołączyć plik skryptu za pomocą znacznika script z atrybutem defer. Pozwala to ćwiczyć zmienne, funkcje i działanie kodu bez tworzenia rozbudowanego projektu.

const stosuje się, gdy zmienna nie będzie ponownie przypisana, a let, gdy jej wartość ma się zmieniać. W nowych projektach nie zaleca się var, chyba że pracujesz świadomie ze starszym kodem. Warto pamiętać, że const blokuje ponowne przypisanie, ale nie unieruchamia zawartości obiektu ani tablicy.

Najpierw wyszukaj element metodą document.querySelector(), a następnie użyj addEventListener() do podpięcia funkcji reagującej na zdarzenie. Na przykład po kliknięciu przycisku można zmienić tekst paragrafu przez właściwość textContent. Podobnie obsługuje się wpisywanie w pole, wysyłanie formularza i najechanie kursorem.

fetch() służy do pobierania danych z serwera i zwraca obietnicę, ponieważ wynik pojawia się po pewnym czasie. Funkcję oznacza się jako async, a await pozwala poczekać na odpowiedź bez blokowania całej aplikacji. Warto sprawdzać właściwość ok odpowiedzi i używać try...catch do obsługi błędów sieci oraz błędnych odpowiedzi serwera.

Oceń artykuł

Ocena: 0.00 Liczba głosów: 0

Tagi:

dom zdarzenia funkcje tablice asynchroniczność

Udostępnij artykuł

Jacek Zając

Jacek Zając

Nazywam się Jacek Zając i od sześciu lat zajmuję się programowaniem webowym. Moja przygoda z tym obszarem zaczęła się od chęci stworzenia własnej strony internetowej, co szybko przerodziło się w pasję do tworzenia aplikacji i rozwiązań, które mogą ułatwiać życie innym. Lubię dzielić się wiedzą, szczególnie w zakresie podstaw programowania oraz budowania responsywnych aplikacji internetowych. W moich tekstach staram się w przystępny sposób wyjaśniać złożone zagadnienia, porównując różne podejścia i technologie, a także zwracając uwagę na aktualne trendy w branży. Zawsze dbam o to, aby informacje, które przekazuję, były rzetelne i zrozumiałe, a także aby były zgodne z najnowszymi standardami. Moim celem jest nie tylko przekazywanie wiedzy, ale także inspirowanie innych do rozwijania swoich umiejętności w programowaniu.

Napisz komentarz