Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Konsola przeglądarki i jej funkcje

Zarządzanie Parkiem Jurajskim nie jest łatwym zadaniem. Gdy pojawiają się problemy z systemem śledzenia dinozaurów lub gdy musimy szybko zdiagnozować, dlaczego protokół blokady nie uruchamia się prawidłowo, kluczową umiejętnością jest debugowanie. Jednym z najważniejszych narzędzi diagnostycznych w JavaScript jest konsola przeglądarki.

W tym ćwiczeniu poznamy narzędzie, które będzie Twoim najlepszym przyjacielem podczas poszukiwania i rozwiązywania problemów - konsolę deweloperską przeglądarki.

Otwieranie konsoli deweloperskiej

Zanim zaczniemy wykorzystywać konsolę, musimy wiedzieć, jak ją otworzyć:

  • Chrome/Edge: <kbd>F12</kbd> lub <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>J</kbd> (Windows/Linux) lub <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>J</kbd> (Mac)
  • Firefox: <kbd>F12</kbd> lub <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>K</kbd> (Windows/Linux) lub <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>K</kbd> (Mac)
  • Safari: <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>C</kbd> (musisz najpierw włączyć narzędzia deweloperskie w ustawieniach)

Po otwarciu zobaczysz kilka zakładek, w tym "Console" (Konsola). To właśnie na niej będziemy się skupiać.

Podstawowe funkcje konsoli

1. console.log() - Twój najlepszy przyjaciel

Najczęściej używaną funkcją konsoli jest

console.log()
. Służy do wyświetlania wartości w konsoli, co jest niezastąpione podczas debugowania:

1// Wyświetlanie prostych wartości
2console.log("System śledzenia dinozaurów uruchomiony");
3console.log(42); // liczba
4console.log(true); // wartość boolowska
5
6// Wyświetlanie wielu wartości naraz
7const dinosaur = { name: "Rex", type: "T-Rex", status: "contained" };
8console.log("Dane dinozaura:", dinosaur, "Aktualizacja:", new Date());
9
10// Łączenie tekstu (interpolacja)
11const sector = "B7";
12const threat = "wysoki";
13console.log(`Wykryto dinozaura w sektorze ${sector}. Poziom zagrożenia: ${threat}`);

W przypadku naszego systemu Parku Jurajskiego możemy używać

console.log()
do śledzenia różnych zdarzeń:

1function trackDinosaur(id, location) {
2  console.log(`Śledzenie dinozaura #${id} w lokalizacji ${location}`);
3
4  // Logika śledzenia...
5  const status = checkContainment(id);
6
7  if (status !== "contained") {
8    console.log(`ALERT: Dinozaur #${id} nie jest w wybiegu! Aktualny status: ${status}`);
9  }
10
11  return status;
12}

2. console.error(), console.warn(), console.info()

Oprócz standardowego

log
, mamy specjalne metody dla różnych poziomów komunikatów:

1// Błędy - zwykle pokazywane na czerwono
2console.error("KRYTYCZNY BŁĄD: Awaria systemu ogrodzeń w sektorze T-Rex!");
3
4// Ostrzeżenia - zwykle pokazywane na żółto
5console.warn("Ostrzeżenie: Poziom naładowania baterii w czujnikach ruchu spada poniżej 20%");
6
7// Informacje - często wyróżnione od zwykłych logów
8console.info("Informacja: Zaplanowano przegląd techniczny systemu na jutro, 8:00");

Ich używanie pomaga wizualnie rozróżnić typy komunikatów w konsoli, co jest szczególnie ważne, gdy mamy do czynienia z dużą ilością logów.

3. console.table() - Przejrzyste wyświetlanie danych tabelarycznych

Gdy mamy do czynienia z tablicami obiektów,

console.table()
jest niezastąpiony:

1// Tablica dinozaurów w naszym parku
2const dinosaurs = [
3  { id: 1, name: "Rex", species: "T-Rex", danger: 9, location: "Wybieg A" },
4  { id: 2, name: "Blue", species: "Velociraptor", danger: 8, location: "Wybieg B" },
5  { id: 3, name: "Delta", species: "Velociraptor", danger: 8, location: "Wybieg B" },
6  { id: 4, name: "Echo", species: "Velociraptor", danger: 7, location: "Wybieg B" },
7  { id: 5, name: "Trike", species: "Triceratops", danger: 4, location: "Wybieg C" }
8];
9
10// Wyświetla piękną tabelę z danymi
11console.table(dinosaurs);
12
13// Możemy też wybrać tylko niektóre kolumny
14console.table(dinosaurs, ["name", "species", "danger"]);

Jest to szczególnie przydatne przy analizie danych, sprawdzaniu wyników zapytań API czy przeglądaniu konfiguracji.

4. console.group() - Grupowanie logów

Gdy mamy wiele powiązanych logów, możemy je zgrupować dla przejrzystości:

1// Monitorowanie konkretnego dinozaura
2function monitorDinosaur(dinosaur) {
3  console.group(`Monitoring: ${dinosaur.name} (${dinosaur.species})`);
4
5  console.log(`Lokalizacja: ${dinosaur.location}`);
6  console.log(`Poziom zagrożenia: ${dinosaur.danger}/10`);
7
8  const healthStatus = checkHealth(dinosaur.id);
9  console.log(`Stan zdrowia: ${healthStatus.status}`);
10
11  if (healthStatus.issues.length > 0) {
12    console.warn(`Wykryto problemy zdrowotne: ${healthStatus.issues.join(', ')}`);
13  }
14
15  const securityStatus = checkSecurity(dinosaur.location);
16  console.log(`Stan zabezpieczeń: ${securityStatus.status}`);
17
18  if (securityStatus.issues.length > 0) {
19    console.error(`Problemy z zabezpieczeniami: ${securityStatus.issues.join(', ')}`);
20  }
21
22  console.groupEnd();
23
24  return { healthStatus, securityStatus };
25}
26
27// Grupowanie można również zagnieżdżać
28function monitorAllDinosaurs(dinosaurs) {
29  console.group('Monitoring wszystkich dinozaurów');
30
31  dinosaurs.forEach(dino => {
32    monitorDinosaur(dino);
33  });
34
35  console.groupEnd();
36}
37
38monitorAllDinosaurs(dinosaurs);

Grupowanie można również zacząć jako zwinięte, używając

console.groupCollapsed()
, co jest przydatne przy dużej liczbie grup.

5. console.time() i console.timeEnd() - Mierzenie czasu wykonania

Czasem potrzebujemy wiedzieć, jak długo trwa wykonanie pewnych operacji:

1// Mierzenie czasu ładowania modułu
2console.time('Ładowanie modułu śledzenia');
3
4loadTrackingModule()
5  .then(() => {
6    console.timeEnd('Ładowanie modułu śledzenia');
7    // Wyświetli np.: "Ładowanie modułu śledzenia: 235.41ms"
8  });
9
10// Możemy mieć wiele równoległych timerów
11console.time('Inicjalizacja systemu');
12console.time('Przetwarzanie danych');
13
14initSystem()
15  .then(() => {
16    console.timeEnd('Inicjalizacja systemu');
17    return processData();
18  })
19  .then(() => {
20    console.timeEnd('Przetwarzanie danych');
21  });

Jest to niezwykle przydatne do identyfikacji wąskich gardeł w aplikacji i optymalizacji wydajności.

6. console.trace() - Śledzenie stosu wywołań

Gdy nie wiesz, skąd dokładnie została wywołana funkcja:

1function monitorFenceStatus(sectorId) {
2  console.trace(`Sprawdzanie statusu ogrodzenia w sektorze ${sectorId}`);
3  // Reszta kodu...
4}
5
6function checkAllFences() {
7  const sectors = ['A1', 'B2', 'C3'];
8  sectors.forEach(monitorFenceStatus);
9}
10
11function dailySecurityCheck() {
12  checkAllFences();
13}
14
15dailySecurityCheck();

console.trace()
wyświetli pełny stos wywołań funkcji, pokazując dokładną ścieżkę wykonania, co jest nieocenione przy debugowaniu skomplikowanych wywołań.

7. console.assert() - Warunkowe komunikaty debugowania

Sprawdza warunek i wyświetla błąd, gdy warunek jest fałszywy:

1function feedDinosaur(dinosaur, foodAmount) {
2  // Upewniamy się, że ilość jedzenia jest wystarczająca dla danego gatunku
3  console.assert(
4    foodAmount >= getMinimumFoodRequirement(dinosaur.species),
5    `Niewystarczająca ilość jedzenia dla ${dinosaur.name}! ` +
6    `Wymagane minimum: ${getMinimumFoodRequirement(dinosaur.species)}kg, ` +
7    `Dostarczono: ${foodAmount}kg`
8  );
9
10  // Reszta kodu...
11}
12
13feedDinosaur(dinosaurs[0], 5); // Jeśli 5kg to za mało, zobaczymy błąd

Jest to przydatne do wczesnegowykrywania potencjalnych problemów, bez przerywania działania programu.

8. console.count() - Liczenie wywołań

Liczenie, ile razy dana funkcja lub blok kodu został wywołany:

1function checkFenceVoltage(sectorId) {
2  console.count(`Sprawdzenie napięcia w sektorze ${sectorId}`);
3  // Reszta kodu...
4}
5
6// Symulacja regularnego sprawdzania
7setInterval(() => checkFenceVoltage('A1'), 5000);
8setInterval(() => checkFenceVoltage('B2'), 8000);

Po każdym wywołaniu zobaczymy w konsoli coś w rodzaju:

1Sprawdzenie napięcia w sektorze A1: 1
2Sprawdzenie napięcia w sektorze A1: 2
3Sprawdzenie napięcia w sektorze B2: 1
4Sprawdzenie napięcia w sektorze A1: 3

Możemy zresetować licznik używając

console.countReset('nazwa')
.

9. console.dir() - Wyświetlanie właściwości obiektu

Gdy chcemy zobaczyć pełną strukturę obiektu:

1const parkSystem = {
2  name: "Jurassic Park",
3  sectors: {
4    A: { dinosaurs: [/*...*/], status: "secure" },
5    B: { dinosaurs: [/*...*/], status: "alert" },
6    //
7  },
8  security: {
9    fences: { status: "online", voltage: 10000 },
10    cameras: { operational: 45, offline: 3 },
11    //
12  },
13  //
14};
15
16// Wyświetla interaktywną, rozwijaną strukturę obiektu
17console.dir(parkSystem);

Ta funkcja jest szczególnie przydatna dla złożonych obiektów, gdyż pozwala na przeglądanie zagnieżdżonych właściwości.

10. Formatowanie komunikatów w konsoli

Konsola obsługuje również podstawowe formatowanie za pomocą specyfikatorów:

1// Formatowanie tekstu z różnymi stylami CSS
2console.log(
3  "%cUWAGA! %cPoziom zagrożenia krytyczny %cin sektorze B!",
4  "color: red; font-size: 20px; font-weight: bold;",
5  "color: orange; font-size: 16px;",
6  "color: black; font-weight: bold;"
7);
8
9// Wyświetlanie zmiennych w komunikacie
10console.log("Dinozaur %s ma poziom zagrożenia %d", "Rex", 9);

Zaawansowane funkcje konsoli

1. Filtrowanie komunikatów

Większość konsoli przeglądarek pozwala na filtrowanie wyświetlanych komunikatów. Możemy filtrować według:

  • Poziomu (Error, Warning, Info, Log)
  • Tekstu (wpisując frazę do wyszukania)
  • Źródła (np. tylko z określonego pliku)

Jest to niezwykle przydatne, gdy mamy do czynienia z dużą ilością logów.

2. Zapisywanie do pliku

Komunikaty z konsoli możemy zazwyczaj zapisać do pliku, co jest przydatne do analizy logów:

  1. Kliknij prawym przyciskiem myszy w konsoli
  2. Wybierz "Save as..." lub "Zapisz jako..."

3. Czyszczenie konsoli

Konsolę można wyczyścić na kilka sposobów:

  • Kliknięcie ikony przekreślonego koła w konsoli
  • Naciśnięcie <kbd>Ctrl</kbd>+<kbd>L</kbd> (gdy konsola jest aktywna)
  • Użycie kodu:
    console.clear()

4. Konsola jako środowisko REPL

Konsola przeglądarki działa również jako REPL (Read-Eval-Print Loop), co oznacza, że możemy bezpośrednio wykonywać w niej kod JavaScript:

1// Bezpośrednio w konsoli
2const dinos = [{name: "Rex"}, {name: "Blue"}];
3dinos.filter(d => d.name === "Blue");
4
5// Definiowanie funkcji
6function alertSecurity(message) {
7  return `[SECURITY ALERT] ${message} - ${new Date().toISOString()}`;
8}
9
10// Używanie tej funkcji
11alertSecurity("Naruszenie ogrodzenia w sektorze C2");

Jest to niezwykle przydatne do testowania małych fragmentów kodu czy debugowania bez modyfikowania kodu źródłowego.

Praktyczna implementacja w naszym systemie Parku Jurajskiego

Stwórzmy praktyczną implementację systemu logowania dla naszego Parku Jurajskiego, który wykorzysta różne funkcje konsoli:

1// Logger dla systemu Parku Jurajskiego
2class JurassicLogger {
3  constructor(moduleName) {
4    this.moduleName = moduleName;
5    this.logCount = 0;
6    this.errorCount = 0;
7    this.warnCount = 0;
8  }
9
10  log(...args) {
11    this.logCount++;
12    console.log(`[${this.moduleName}] `, ...args);
13  }
14
15  error(...args) {
16    this.errorCount++;
17    console.error(`[${this.moduleName}] ERROR:`, ...args);
18  }
19
20  warn(...args) {
21    this.warnCount++;
22    console.warn(`[${this.moduleName}] WARNING:`, ...args);
23  }
24
25  info(...args) {
26    console.info(`[${this.moduleName}] INFO:`, ...args);
27  }
28
29  startGroup(label) {
30    console.group(`[${this.moduleName}] ${label}`);
31  }
32
33  endGroup() {
34    console.groupEnd();
35  }
36
37  startTimer(label) {
38    console.time(`[${this.moduleName}] ${label}`);
39  }
40
41  endTimer(label) {
42    console.timeEnd(`[${this.moduleName}] ${label}`);
43  }
44
45  table(data, columns) {
46    console.log(`[${this.moduleName}] Dane tabelaryczne:`);
47    console.table(data, columns);
48  }
49
50  getStats() {
51    return {
52      moduleName: this.moduleName,
53      logs: this.logCount,
54      errors: this.errorCount,
55      warnings: this.warnCount
56    };
57  }
58
59  trace(message) {
60    console.log(`[${this.moduleName}] TRACE: ${message}`);
61    console.trace();
62  }
63
64  assert(condition, message) {
65    console.assert(condition, `[${this.moduleName}] Assertion failed: ${message}`);
66  }
67
68  // Formatowanie specjalne dla alertów bezpieczeństwa
69  securityAlert(message, level = 'warning') {
70    const styles = {
71      warning: "background: #FFA500; color: black; padding: 2px 5px; border-radius: 3px;",
72      critical: "background: #FF0000; color: white; padding: 2px 5px; border-radius: 3px; font-weight: bold;",
73      info: "background: #0066FF; color: white; padding: 2px 5px; border-radius: 3px;"
74    };
75
76    console.log(
77      `%c[${this.moduleName}] SECURITY ALERT %c${message}`,
78      styles[level] || styles.warning,
79      "color: black;"
80    );
81  }
82}
83
84// Przykład użycia
85const securityLogger = new JurassicLogger('ParkSecurity');
86const dinosaurLogger = new JurassicLogger('DinosaurTracker');
87const systemLogger = new JurassicLogger('MainSystem');
88
89// Inicjalizacja systemu
90systemLogger.startTimer('Inicjalizacja systemu');
91systemLogger.log('Rozpoczynanie inicjalizacji systemów Parku Jurajskiego...');
92
93// Symulacja inicjalizacji podsystemów
94setTimeout(() => {
95  systemLogger.info('Podsystemy uruchomione');
96  systemLogger.endTimer('Inicjalizacja systemu');
97
98  // Informacje o dinozaurach
99  const dinoData = [
100    { id: 'TRX-01', name: 'Rex', species: 'T-Rex', status: 'contained', healthLevel: 92 },
101    { id: 'VEL-01', name: 'Blue', species: 'Velociraptor', status: 'contained', healthLevel: 87 },
102    { id: 'VEL-02', name: 'Delta', species: 'Velociraptor', status: 'sedated', healthLevel: 65 },
103    { id: 'TRI-01', name: 'Sarah', species: 'Triceratops', status: 'contained', healthLevel: 95 }
104  ];
105
106  dinosaurLogger.startGroup('Raport statusu dinozaurów');
107  dinosaurLogger.table(dinoData);
108
109  // Sprawdzanie stanu zdrowia dinozaurów
110  dinoData.forEach(dino => {
111    dinosaurLogger.startGroup(`Dinozaur: ${dino.name}`);
112
113    if (dino.healthLevel < 70) {
114      dinosaurLogger.warn(`Poziom zdrowia dinozaura ${dino.name} jest niski: ${dino.healthLevel}%`);
115    } else {
116      dinosaurLogger.log(`Stan zdrowia: ${dino.healthLevel}%`);
117    }
118
119    if (dino.status !== 'contained') {
120      dinosaurLogger.error(`Dinozaur ${dino.name} nie jest w wybiegu! Status: ${dino.status}`);
121      securityLogger.securityAlert(`Dinozaur ${dino.name} (${dino.species}) ma status: ${dino.status}`, 'critical');
122    }
123
124    dinosaurLogger.endGroup();
125  });
126
127  dinosaurLogger.endGroup();
128
129  // Sprawdzanie systemów bezpieczeństwa
130  securityLogger.startGroup('Systemy bezpieczeństwa');
131
132  const fenceStatus = { sector: 'B', voltage: 9800, status: 'active' };
133  securityLogger.log(`Status ogrodzenia w sektorze ${fenceStatus.sector}: ${fenceStatus.status}`);
134  securityLogger.assert(
135    fenceStatus.voltage >= 10000,
136    `Napięcie ogrodzenia w sektorze ${fenceStatus.sector} jest zbyt niskie: ${fenceStatus.voltage}V (min. 10000V)`
137  );
138
139  // Symulacja naruszenia bezpieczeństwa
140  if (Math.random() > 0.7) {
141    securityLogger.trace('Wykryto nieautoryzowany dostęp do panelu sterowania');
142    securityLogger.securityAlert('Wykryto nieautoryzowany dostęp do systemów kontroli!', 'critical');
143  }
144
145  securityLogger.endGroup();
146
147  // Wyświetlanie statystyk logów
148  systemLogger.startGroup('Statystyki logów');
149  console.table([
150    securityLogger.getStats(),
151    dinosaurLogger.getStats(),
152    systemLogger.getStats()
153  ]);
154  systemLogger.endGroup();
155
156}, 2000);

Integracja z frameworkami

Nowoczesne frameworki jak React czy Vue mają własne integracje z konsolą, które dostarczają dodatkowych informacji debugujących:

React DevTools

React DevTools dodaje do konsoli przeglądarki specjalne narzędzia do inspekcji komponentów React, stanu, propów i drzewa komponentów. To niezastąpione narzędzie dla każdego dewelopera React.

Vue DevTools

Podobnie Vue ma własne narzędzia deweloperskie, które pozwalają na inspekcję komponentów, stanu Vuex i innych aspektów aplikacji Vue.

Logowanie produkcyjne i deweloperskie

W rzeczywistych aplikacjach warto rozdzielić logowanie deweloperskie od produkcyjnego:

1// logger.js
2class Logger {
3  constructor(isProduction = process.env.NODE_ENV === 'production') {
4    this.isProduction = isProduction;
5  }
6
7  log(...args) {
8    if (!this.isProduction) {
9      console.log(...args);
10    }
11  }
12
13  // W przypadku błędów krytycznych, logujemy nawet na produkcji
14  error(...args) {
15    console.error(...args);
16
17    if (this.isProduction) {
18      // Na produkcji możemy wysłać błędy do usługi monitorowania
19      this.sendToErrorMonitoring(args);
20    }
21  }
22
23  // ...inne metody
24
25  sendToErrorMonitoring(errorData) {
26    // Implementacja wysyłania do Sentry, LogRocket itp.
27  }
28}
29
30export default new Logger();

Podsumowanie

Konsola przeglądarki to potężne narzędzie, które znacznie ułatwia debugowanie i monitorowanie aplikacji JavaScript. W kontekście naszego Parku Jurajskiego, dobre praktyki logowania mogą być różnicą między sprawnie działającym parkiem a... cóż, scenariuszem znanym z filmów!

Najważniejsze funkcje do zapamiętania:

  • console.log()
    - podstawowe logowanie
  • console.error()
    ,
    console.warn()
    ,
    console.info()
    - różne poziomy komunikatów
  • console.table()
    - przejrzyste wyświetlanie danych
  • console.group()
    - organizacja powiązanych logów
  • console.time()
    i
    console.timeEnd()
    - mierzenie wydajności
  • console.trace()
    - diagnozowanie skąd pochodzi wywołanie
  • console.assert()
    - warunkowe komunikaty debugowania

Pamiętaj, aby regularnie używać konsoli podczas tworzenia aplikacji - pomoże Ci to szybciej wykrywać i naprawiać błędy, zanim dinozaury znajdą lukę w Twoim kodzie!

Przejdź do CodeWorlds