Debugowanie kodu
Pisząc kod co chwila będziemy natrafiać na różnego rodzaju błędy. Aby sobie z nimi radzić powinniśmy umieć debugować nasz kod. Poniżej zajmiemy się kilkoma metodami podejścia do takiego zadania.
console
To chyba najprostsza metoda do testowania kodu, którą już trochę omawialiśmy w rozdziale o debuggerze, a i którą non stop używam w listingach.
//wypisanie tekstu
const text = "Moja mała świnka";
console.log(text);
//wypisywanie całego obiektu
console.log(window);
//wypisanie wielu rzeczy po przecinku
const a = 10;
const b = 20;
console.log("a: ", a, "b: ", b);
Wypisując jakieś rzeczy w konsoli wraz z tekstem warto zamiast +
używać przecinka. Dzięki temu wypisywany element nie będzie konwertowany na tekst i nie dostaniemy w konsoli głupot.
const obj = { name: "test" }
//zamiast
console.log("Wynik: " + obj); //"Wynik: [object Object]"
//użyj
console.log("Wynik:", obj); //"Wynik:", {name: "test"}
Przy okazji warto tutaj przypomnieć sobie ułatwienie pracy, które pokazałem wam w dziale o debuggerze.
Obiekt console udostępnia nam też kilka innych - równie przydatnych metod, które opisane są na stronie https://developer.mozilla.org/pl/docs/Web/API/Console.
Jeżeli zapomnimy ich listę, wystarczy w konsoli debuggera wpisać słowo console
i zbadać wypisany obiekt. W pracy codziennej w większości przypadków wystarczą:
console.log() //klasyk
console.dir() //do bardziej szczegółowego wypisywania obiektów. Szczególnie przydatna przy wypisywaniu elementów DOM
console.table() //wypisuje ładnie sformatowany stan tabeli w danym momencie
Debugowanie za pomocą debuggera
Debugowanie za pomocą console sprawdza się w wielu sytuacjach, i wcale nie trzeba się go wstydzić. Nie zawsze jest jednak optymalną metodą odpluskwiania kodu.
Gdy pojawi się jakiś komunikat, błąd lub informacja, w konsoli po prawej stronie takiego komunikatu będziemy mieli pokazaną linię w kodzie, z której nastąpiło wypisanie danej informacji. Gdy ją klikniemy zostaniemy przeniesieni do zakładki Sources.


Aby debugować kod, musimy zatrzymać nasz skrypt w danym miejscu. Możemy to zrobić na kilka sposobów.
Możemy użyć w kodzie słowa kluczowego debugger:
const ob1 = { ... }
const ob2 = { ... }
debugger; //zatrzymujemy wykonywanie kodu
const ob3 = {...ob1, ...ob2};
debugger; //znowu zatrzymujemy - a co!
Kolejnym sposobem, który daje podobne efekty jest użycie tak zwanych breakpointów. Po kliknięciu w numer danej linii, stawiamy w niej breakpoint (niebieski znacznik).
Jeżeli skrypt ponownie się wykona (np. strona zostanie przeładowana, dana funkcja zostanie odpalona itp.), skrypt zostanie zatrzymany w danej linii (dana linijka jeszcze się nie wykona, a kursor stanie na jej początku).

Po zatrzymaniu skryptu (dowolną metodą) najeżdżając na zmienne możemy badać ich aktualny stan:

W niektórych przypadkach możemy chcieć zatrzymywać kod na danym breakpoincie tylko w określonym warunku. Powiedzmy, że chcemy zbadać poniższych użytkowników, ale tylko w sytuacji, gdy ich punkty wynoszą poniżej 50:
const users = [
{ name : "Marcin", points : 51 },
{ name : "Weronika", points : 87 },
{ name : "Piotr", points : 65 },
{ name : "Monika", points : 46 },
{ name : "Anna", points : 98 },
]
users.forEach(function(user) {
console.log(user.name, user.points);
})
Jeżeli teraz postawimy breakpoint w linijce z console.log(), skrypt będzie się zatrzymywać w tej linii przy każdej iteracji naszej pętli. Domyślnie breakpoint taki stawiany jest na początku linii. Oznacza to, że kod zostanie zatrzymany przed wykonaniem danej linii kodu. Gdy postawisz taki breakpoint w większości przypadków będziesz mógł postawić dodatkowe breakpoiny wewnątrz danej linii.
Czasami (szczególnie w przypadku pętli po długich tablicach) może to być mocno problematyczne. Możemy jednak kliknąć na taki niebieski breakpoint prawym przyciskiem i wybrać "Edit breakpoint".

Pojawi się okienko, do którego możemy dodać dodatkowy warunek, który jeżeli będzie spełniony, aktywuje breakpoint.

Breakpoint zmieni kolor na pomarańczowy i od tej pory będzie aktywny tylko w przypadku gdy nasz warunek będzie spełniony.
Aby wznowić działanie skryptów kliknij ikonkę play (znajduje się po prawej stronie zakładki Sources):

lub naciśnij klawisz F8. Skrypt się wznowi i ewentualnie zatrzyma na kolejnym breakpoincie.
Jak widzisz poza ikonką wznawiającą działanie skryptów po prawej stronie mamy też kilka innych.
![]() |
Wznawia działanie kodu |
![]() |
Jeżeli w danej linii znajduje się wywołanie funkcji, debugger wykona ją, ale nie przeniesie kursora do jej wnętrza, a przeskoczy nim do następnej instrukcji w kodzie. Jeżeli nie ma takiego wywołania, ikonka zachowa się jak przejście do następnego kroku. |
![]() |
Przechodzi kursorem do wnętrza funkcji, lub zachowuje się jak przejście do kolejnego kroku |
![]() |
Wychodzi z danej funkcji i przechodzi do kolejnej linii kodu (czyli poza linię, gdzie dana funkcja została wywołana) |
![]() |
Wyłącza na chwilę breakpointy. Pomocne gdy mamy nastawiane naście takich breakpointów i chcemy na chwilę sprawdzić jak się strona zachowuje bez zatrzymywania |
![]() |
Czy kod ma się zatrzymywać na błędach. Jeżeli włączymy tą opcję, kod będzie zatrzymywał się tuż przed pokazaniem czerwonych błędów w konsoli |
Zauważ, że po ustawieniu breakpointów, pojawiają się one nie tylko jako niebieskie punkty na numerycznej linii, ale też jako lista w prawej części zakładki Sources:

Sekcja ta ma jeszcze kilka ciekawych rzeczy do zaoferowania, które są bardzo przydatne podczas debugowania.
Watch, CallStack, Scope i XHR
Pierwsza z góry to sekcja Watch.

Służy ona do obserwowania zmiennych. Za pomocą plusa możemy tam podać nazwę zmiennej, którą chcemy nasłuchiwać, a dzięki temu właśnie w tym miejscu będziemy mogli w wygodny sposób sprawdzić jej stan w określonym momencie.
Kolejna sekcja - CallStack - pokazuje kolejność odpalanych funkcji. Funkcje w JavaScript (jak i w innych językach) mogą być odpalane z wnętrza innych funkcji itp. Tutaj możemy podejrzeć właśnie taką kolejność.
Bardzo użyteczna sekcja Scope pozwala nam łatwo sprawdzać zmienne w danym scope. Co to oznacza? Powiedzmy, że postawimy breakpoint wewnątrz danej funkcji. Dzięki tej sekcji w wygodny sposób sprawdzimy, jakie zmienne są używane wewnątrz tej funkcji.
Jeżeli chcesz sprawdzić jej działanie, kliknij w poniższy przycisk. Za pomocą instrukcji debugger postawiłem dla ciebie breakpoint w przykładowej funkcji. Po jego kliknięciu sprawdź gdzie zatrzymał się skrypt i co znajduje się w sekcji Scope.
Kolejną sekcją jest XHR/fetch Breakpoints. Możemy w niej ustawiać breakpointy dla requestów, które będą miały w adresie szukaną frazę.
DOM Breakpoints
Poza breakpointami i instrukcją debugger istnieją też inne sposoby na zatrzymanie skryptu w odpowiednim momencie.
Po pierwsze możemy nakazać przeglądarce zatrzymanie wykonywania skryptów, jeżeli zostanie zmodyfikowany dany element w drzewie DOM. Aby to zrobić wystarczy w zakładce debuggera Elements kliknąć prawym przyciskiem myszy wybrany element, i z menu kontekstowego wybrać opcję Break on.

Poszczególne opcje oznaczają:
subtree modification | zatrzymaj działanie skryptów, gdy zmieni się struktura html danego elementu i jego zawartości (dzieci i zagnieżdżonych elementów) |
---|---|
attribute modifications | zatrzymaj skrypty, jeżeli zmieni się zawartość atrybutów danego elementu (np. skrypt zmieni style danego elementu) |
node removal | - zatrzymaj skrypt jeżeli dany element zostanie usunięty |
Sprawdźmy to na przykładzie.
Poniżej mamy 3 przyciski. Pierwszy po kliknięciu zmienia tło (czyli dodaje atrybut style). Drugi zmienia swoją zawartość html, a trzeci po kliknięciu jest usuwany.
Ustaw im odpowiednie "Break on". Zauważ, że po ustawieniu "Break on" dla danego elementu, pojawi się przy nim w zakładce Elements niebieska kropka.

Jeżeli takie breakpointy bazujące na zmianach html ustawimy w zakładce Elements, pojawią się one też jako lista z prawej strony w zakładce Source.

Dodatkowo w zakładce Elements gdy badasz dany element po prawej stronie będziesz miał style. Nad prawą kolumną masz zakładki. Style to style, w Computed zobaczysz jak te style widzi przeglądarka. Kolejną zakładką jest Event Listeners, w której możesz podejrzeć listę używanych na danej stronie zdarzeń.
Event Listener
Wracamy do zakładki Source. Poniżej sekcji Breakpoints znajduje się przydatna sekcja Event Listener Breakpoints, która służy do ustawiania breakpointów na dane zdarzenia. Wyobraź sobie, że po kliknięciu, najechaniu kursorem czy dowolnej innej czynności wykonywany jest jakiś kod JavaScript. Skąd mamy jednak wiedzieć, gdzie dana funkcja się znajduje? Wystarczy w sekcji tej znaleźć zdarzenie Click (znajduje się w grupie Mouse) i go zaznaczyć. Od tej pory jeżeli pod dane zdarzenie podpięty jest jakiś kod, nasz kod zostanie w tym miejscu zatrzymany.

Sprawdźmy to. Włącz breakpoint dla zdarzeń click i kliknij w poniższy przycisk. Dzięki temu kod zostanie zatrzymany w super tajnej funkcji, której miejsca nikt nigdy nie odkrył (a warto)...
Opcja ta jest mega przydatna na obcych stronach, gdzie zaciekawi nas jakiś efekt. Wystarczy włączyć breakpoint na dane zdarzenie i zacząć badać...
Debugowanie w Visual Studio Code
Jeżeli używamy edytora Visual Studio Code, debugowanie naszego kodu możemy sobie dodatkowo nieco umilić. Istnieje bowiem dodatek zwący się Debugger for Chrome, który umożliwia debugowanie kodu bezpośrednio w edytorze.
Gdy go zainstalujemy, wystarczy przejść w tryb debugowania (klawisz F5 lub wybranie z górnego menu opcji Debug->Start Debuging), a naszym oczom ukaże sie widok z oknami o znaczeniu podobnym do tego, co omawialiśmy powyżej:

na górze lewej sekcji znajdują się opcje służące do skonfigurowania połączenia oraz jego odpalenia:

Po kliknięciu w trybik zostanie otwarty plik z przykładową konfiguracją.
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://127.0.0.6:8080",
"webRoot": "${workspaceFolder}"
}
]
}
Aby móc debugować w edytorze, musimy naszą stronę wcześniej odpalić na jakimś serwerze lokalnym.
Jeżeli pracujemy z jakimś frameworkiem JS - np. Reactem, praktycznie zawsze będziemy mieli odpalony taki serwer (np. react-dev-server).
Jeżeli pracujemy bardziej klasycznie, możemy skorzystać z jednego z wielu serwerów lokalnych. Pomówimy sobie na ten temat w tym rozdziale.
Gdy już odpalimy naszą stronę, musimy adres na jakim została odpalona wpisać w powyższej konfiguracji w parametrze url.
Po podaniu adresu i zapisaniu konfiguracji, możemy odpalić połączenie poprzez zieloną strzałkę. Gdy wszystko pójdzie dobrze, nasza strona powinna się otworzyć w nowym oknie przeglądarki.
Od tej pory możemy zacząć debugować bezpośrednio w edytorze. Oznacza to, że breakpointy możemy stawiać nie tylko w Source, ale też klikając obok numerów linii bezpośrednio w edytorze (pojawią się czerwone kropki), a i boczne okna staną się dla nas pomocne.

Quokka
Inne możliwości ułatwiające pracę z debugowaniem daje nam np. dodatek o nazwie Quokka. Po jego instalacji, będzie nam pokazywał wynik danego równania tuż obok linii.

Nie sprawdzi się to w każdym rodzaju skryptu, ale dość często może być całkiem wygodnym rozwiązaniem.
Trening czyni mistrza
Jeżeli chcesz sobie potrenować zdobytą wiedzę, zadania znajdują się w repozytorium pod adresem: https://github.com/kartofelek007/zadania