Kurs JavaScript i TypeScript · Moduł 2: Funkcje, tablice i obiekty

Parametry i argumenty funkcji w JavaScript

9 min czytania
W tej lekcji7

Witaj ponownie w Parku Jurajskim! W module 1 poznaliśmy podstawy funkcji w JavaScript. Teraz zagłębimy się w to, jak funkcje mogą przyjmować dane i pracować z nimi - co jest kluczowe dla tworzenia elastycznych i wydajnych systemów zarządzania parkiem.

Różnica między parametrami a argumentami

Choć terminy "parametry" i "argumenty" są często używane zamiennie, istnieje między nimi subtelna różnica:

  • Parametry to zmienne zdefiniowane w deklaracji funkcji
  • Argumenty to rzeczywiste wartości przekazywane do funkcji podczas jej wywołania
1// name i species to parametry
2function addDinosaur(name, species) {
3  console.log(`Dodawanie nowego dinozaura: ${name} (${species})`);
4  // Kod dodający dinozaura do systemu
5}
6
7// "Blue" i "Velociraptor" to argumenty
8addDinosaur("Blue", "Velociraptor");

Parametry podstawowe

JavaScript oferuje kilka sposobów pracy z parametrami funkcji:

1. Parametry obowiązkowe i opcjonalne

W JavaScript wszystkie parametry są technicznie opcjonalne, ale możemy zaprojektować funkcje, które traktują niektóre parametry jako obowiązkowe:

1function feedDinosaur(dinoName, foodType) {
2  // Sprawdzenie czy parametry zostały podane
3  if (dinoName === undefined) {
4    throw new Error("Musisz podać nazwę dinozaura!");
5  }
6
7  // foodType jest opcjonalny, używamy wartości domyślnej jeśli nie został podany
8  const food = foodType || "mięso";
9
10  console.log(`Karmienie ${dinoName}, pokarm: ${food}`);
11  return `${dinoName} został nakarmiony`;
12}
13
14// Wywołania
15feedDinosaur("Rex", "żywe bydło"); // "Karmienie Rex, pokarm: żywe bydło"
16feedDinosaur("Blue"); // "Karmienie Blue, pokarm: mięso"
17// feedDinosaur(); // Error: Musisz podać nazwę dinozaura!

2. Parametry domyślne (ES6+)

Od ES6 (ES2015), JavaScript obsługuje parametry domyślne, które upraszczają definiowanie wartości domyślnych:

1function scheduleFeeding(dinoName, foodType = "mięso", time = "12:00") {
2  console.log(`Zaplanowano karmienie ${dinoName}, pokarm: ${foodType}, godzina: ${time}`);
3  return {
4    dino: dinoName,
5    food: foodType,
6    scheduledTime: time
7  };
8}
9
10// Wywołania
11scheduleFeeding("Triceratops", "rośliny", "10:30");
12// "Zaplanowano karmienie Triceratops, pokarm: rośliny, godzina: 10:30"
13
14scheduleFeeding("Raptor");
15// "Zaplanowano karmienie Raptor, pokarm: mięso, godzina: 12:00"
16
17scheduleFeeding("Rex", undefined, "15:45");
18// "Zaplanowano karmienie Rex, pokarm: mięso, godzina: 15:45"

Parametry domyślne są oceniane w czasie wywołania funkcji, co oznacza, że możesz używać wyrażeń, a nawet innych parametrów:

1function prepareEnclosure(dinoType, securityLevel = calculateSecurityLevel(dinoType), capacity = securityLevel * 2) {
2  console.log(`Przygotowywanie zagrody dla ${dinoType}...`);
3  console.log(`Poziom zabezpieczeń: ${securityLevel}`);
4  console.log(`Pojemność: ${capacity} osobników`);
5}
6
7function calculateSecurityLevel(dinoType) {
8  const dangerousSpecies = ["Tyrannosaurus", "Velociraptor", "Spinosaurus"];
9  return dangerousSpecies.includes(dinoType) ? 5 : 3;
10}
11
12// Przygotowanie zagrody dla T-Rexa (wysoki poziom bezpieczeństwa)
13prepareEnclosure("Tyrannosaurus");
14// Poziom zabezpieczeń: 5, Pojemność: 10 osobników
15
16// Przygotowanie zagrody dla Triceratopsa (standardowy poziom bezpieczeństwa)
17prepareEnclosure("Triceratops");
18// Poziom zabezpieczeń: 3, Pojemność: 6 osobników
19
20// Przygotowanie niestandardowej zagrody
21prepareEnclosure("Velociraptor", 6, 4);
22// Poziom zabezpieczeń: 6, Pojemność: 4 osobników

Obsługa zmiennej liczby argumentów

W systemach tak złożonych jak Park Jurajski, czasem potrzebujemy funkcji, które mogą przyjmować zmienną liczbę argumentów.

1. Obiekt arguments

Każda zwykła funkcja (zadeklarowana słowem function) ma dostęp do specjalnego obiektu arguments, który zawiera wszystkie przekazane do niej argumenty. Funkcje strzałkowe nie mają własnego arguments:

1function alertSecurityTeam() {
2  console.log(`Wysyłanie alertu do ${arguments.length} członków zespołu bezpieczeństwa.`);
3
4  for (let i = 0; i < arguments.length; i++) {
5    console.log(`Powiadamianie: ${arguments[i]}`);
6  }
7}
8
9// Możemy wywołać funkcję z dowolną liczbą argumentów
10alertSecurityTeam("John Hammond", "Robert Muldoon", "Ellie Sattler");
11// Wysyłanie alertu do 3 członków zespołu bezpieczeństwa.
12// Powiadamianie: John Hammond
13// Powiadamianie: Robert Muldoon
14// Powiadamianie: Ellie Sattler

Obiekt arguments nie jest prawdziwą tablicą, ale podobnym do tablicy obiektem (array-like object). Można go konwertować do tablicy:

1function logVisitors() {
2  // Konwersja arguments na tablicę
3  const visitorsArray = Array.from(arguments);
4  // lub: const visitorsArray = [...arguments]; // (ES6+)
5
6  console.log(`Zalogowano ${visitorsArray.length} gości.`);
7
8  // Teraz możemy używać metod tablicowych
9  visitorsArray.forEach((visitor, index) => {
10    console.log(`Gość #${index + 1}: ${visitor}`);
11  });
12}
13
14logVisitors("Ian Malcolm", "Alan Grant", "Dennis Nedry");
15// Zalogowano 3 gości.
16// Gość #1: Ian Malcolm
17// Gość #2: Alan Grant
18// Gość #3: Dennis Nedry

2. Parametr rest (ES6+)

Nowszy i bardziej elegancki sposób obsługi zmiennej liczby argumentów to parametr rest, wprowadzony w ES6:

1function trackDinosaurs(...dinosaurs) {
2  console.log(`Śledzenie ${dinosaurs.length} dinozaurów:`);
3
4  dinosaurs.forEach((dino, index) => {
5    console.log(`${index + 1}. Lokalizowanie: ${dino}`);
6  });
7}
8
9trackDinosaurs("T-Rex", "Velociraptor", "Triceratops", "Brachiosaurus");
10// Śledzenie 4 dinozaurów:
11// 1. Lokalizowanie: T-Rex
12// 2. Lokalizowanie: Velociraptor
13// 3. Lokalizowanie: Triceratops
14// 4. Lokalizowanie: Brachiosaurus

Parametr rest zbiera wszystkie pozostałe argumenty do tablicy. Musi być ostatnim parametrem w funkcji, ale może być poprzedzony zwykłymi parametrami:

1function assignTasks(teamLead, date, ...teamMembers) {
2  console.log(`Zadania na ${date} dla zespołu prowadzonego przez ${teamLead}:`);
3
4  teamMembers.forEach(member => {
5    console.log(`- ${member}: ${generateRandomTask()}`);
6  });
7}
8
9function generateRandomTask() {
10  const tasks = [
11    "Sprawdzenie ogrodzeń",
12    "Karmienie dinozaurów",
13    "Zbieranie próbek DNA",
14    "Monitorowanie zdrowia zwierząt",
15    "Konserwacja systemów bezpieczeństwa"
16  ];
17  return tasks[Math.floor(Math.random() * tasks.length)];
18}
19
20assignTasks("Dr. Henry Wu", "2023-06-15", "John", "Sarah", "Michael");
21// Zadania na 2023-06-15 dla zespołu prowadzonego przez Dr. Henry Wu:
22// - John: Sprawdzenie ogrodzeń
23// - Sarah: Karmienie dinozaurów
24// - Michael: Monitorowanie zdrowia zwierząt

Operator rozproszenia (spread)

Operator spread (...) jest przeciwieństwem parametru rest. Zamiast zbierać argumenty w tablicę, rozkłada tablicę (lub inny iterowalny obiekt) na poszczególne argumenty:

1function monitorVitalSigns(dinoName, temperature, heartRate, respirationRate) {
2  console.log(`Monitoring parametrów życiowych dla: ${dinoName}`);
3  console.log(`- Temperatura: ${temperature}°C`);
4  console.log(`- Tętno: ${heartRate} uderzeń/min`);
5  console.log(`- Częstość oddychania: ${respirationRate} oddechów/min`);
6
7  // Analiza parametrów i generowanie raportu
8  if (temperature > 39 || heartRate > 140 || respirationRate > 30) {
9    return "ALERT: Parametry życiowe poza normą!";
10  }
11  return "Parametry życiowe w normie.";
12}
13
14// Tablica z danymi o parametrach życiowych
15const rexVitals = ["T-Rex", 38.2, 115, 22];
16
17// Bez operatora spread
18monitorVitalSigns(rexVitals[0], rexVitals[1], rexVitals[2], rexVitals[3]);
19
20// Z operatorem spread - rozkłada tablicę na oddzielne argumenty
21monitorVitalSigns(...rexVitals);

Operator spread jest również przydatny przy łączeniu tablic lub obiektów:

1// Łączenie danych o dinozaurach z różnych systemów
2const basicDinoData = {
3  id: "VLR-01",
4  name: "Blue",
5  species: "Velociraptor"
6};
7
8const healthData = {
9  weight: 100,
10  health: "Dobry",
11  lastCheckup: "2023-05-10"
12};
13
14const behavioralData = {
15  temperament: "Agresywny",
16  packStatus: "Beta",
17  trainingLevel: "Zaawansowany"
18};
19
20// Tworzenie kompletnego obiektu danych o dinozaurze
21const completeProfile = {
22  ...basicDinoData,
23  ...healthData,
24  ...behavioralData,
25  updatedAt: new Date().toISOString()
26};
27
28console.log(completeProfile);
29// {
30//   id: "VLR-01",
31//   name: "Blue",
32//   species: "Velociraptor",
33//   weight: 100,
34//   health: "Dobry",
35//   lastCheckup: "2023-05-10",
36//   temperament: "Agresywny",
37//   packStatus: "Beta",
38//   trainingLevel: "Zaawansowany",
39//   updatedAt: "2023-06-15T10:30:00.000Z"
40// }

Destrukturyzacja parametrów obiektowych

Gdy funkcje przyjmują wiele parametrów, często łatwiej jest przekazać je jako obiekt. Destrukturyzacja (ES6+) pozwala na eleganckie wyodrębnienie tych wartości:

1// Funkcja akceptująca obiekt opcji
2function createDinosaurEnclosure({ species, capacity, securityLevel, location, features = [] }) {
3  console.log(`Tworzenie zagrody dla gatunku: ${species}`);
4  console.log(`Pojemność: ${capacity} osobników`);
5  console.log(`Poziom zabezpieczeń: ${securityLevel}/5`);
6  console.log(`Lokalizacja: ${location}`);
7
8  if (features.length > 0) {
9    console.log("Dodatkowe funkcje zagrody:");
10    features.forEach(feature => console.log(`- ${feature}`));
11  }
12
13  return `Zagroda dla ${species} została utworzona w lokalizacji ${location}`;
14}
15
16// Wywołanie z obiektem opcji
17const enclosureResult = createDinosaurEnclosure({
18  species: "Triceratops",
19  capacity: 6,
20  securityLevel: 3,
21  location: "Sektor B",
22  features: ["Zbiornik wodny", "Roślinność z okresu kredy", "Platforma obserwacyjna"]
23});
24
25console.log(enclosureResult);
26// "Zagroda dla Triceratops została utworzona w lokalizacji Sektor B"

Możemy również ustawić domyślne wartości dla całego obiektu:

1function scheduleLabTest({
2  specimenId,
3  testType = "DNA",
4  priority = "Normal",
5  assignedTo = "Dr. Wu"
6} = {}) {  // Domyślny pusty obiekt zapobiega błędom, gdy nie podamy argumentu
7
8  console.log(`Zaplanowano test ${testType} dla próbki #${specimenId}`);
9  console.log(`Priorytet: ${priority}`);
10  console.log(`Przypisany do: ${assignedTo}`);
11
12  return `Test zaplanowany. ID testu: TEST-${specimenId}-${Date.now()}`;
13}
14
15// Wywołanie z wszystkimi opcjami
16scheduleLabTest({
17  specimenId: "VLR-42",
18  testType: "Sekwencjonowanie genomu",
19  priority: "Wysoki",
20  assignedTo: "Dr. Sattler"
21});
22
23// Wywołanie z tylko wymaganym parametrem
24scheduleLabTest({ specimenId: "TRX-05" });
25
26// Wywołanie bez argumentów (zadziała dzięki domyślnemu pustemu obiektowi)
27// scheduleLabTest(); // Bez domyślnego pustego obiektu to by wywołało błąd

Praktyczny przykład: System zarządzania incydentami

Połączmy poznane koncepcje, tworząc kompleksowy system zarządzania incydentami dla Parku Jurajskiego:

1// System zarządzania incydentami
2const incidentManager = (function() {
3  // Prywatna tablica incydentów
4  const incidents = [];
5
6  // Prywatne funkcje pomocnicze
7  function generateIncidentId() {
8    return `INC-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
9  }
10
11  function notifyTeam(incidentType, location, ...personnel) {
12    console.log(`ALERT: Incydent typu "${incidentType}" w lokalizacji "${location}"`);
13
14    if (personnel.length > 0) {
15      console.log(`Powiadamianie personelu: ${personnel.join(', ')}`);
16    } else {
17      console.log("Powiadamianie całego personelu bezpieczeństwa");
18    }
19  }
20
21  // Publiczne API
22  return {
23    // Metoda do raportowania nowego incydentu
24    reportIncident: function({
25      type,
26      location,
27      description,
28      severity = "Średni",
29      reportedBy,
30      affectedAssets = [],
31      notifyPersonnel = []
32    }) {
33      const incidentId = generateIncidentId();
34
35      const incident = {
36        id: incidentId,
37        type,
38        location,
39        description,
40        severity,
41        reportedBy,
42        affectedAssets,
43        status: "Nowy",
44        reportedAt: new Date().toISOString(),
45        resolvedAt: null
46      };
47
48      incidents.push(incident);
49
50      // Powiadomienie personelu
51      notifyTeam(type, location, ...notifyPersonnel);
52
53      return {
54        incidentId,
55        message: `Incydent #${incidentId} został zarejestrowany`
56      };
57    },
58
59    // Metoda do aktualizacji statusu incydentu
60    updateIncidentStatus: function(incidentId, newStatus, resolvedBy = null) {
61      const incident = incidents.find(inc => inc.id === incidentId);
62
63      if (!incident) {
64        return { success: false, message: "Incydent nie znaleziony" };
65      }
66
67      incident.status = newStatus;
68
69      if (newStatus === "Rozwiązany") {
70        incident.resolvedAt = new Date().toISOString();
71        incident.resolvedBy = resolvedBy;
72      }
73
74      return {
75        success: true,
76        message: `Status incydentu #${incidentId} zaktualizowany na "${newStatus}"`
77      };
78    },
79
80    // Metoda do pobierania informacji o incydencie
81    getIncidentInfo: function(incidentId) {
82      const incident = incidents.find(inc => inc.id === incidentId);
83
84      if (!incident) {
85        return null;
86      }
87
88      return { ...incident }; // Zwracamy kopię, aby uniknąć modyfikacji oryginału
89    },
90
91    // Metoda do pobierania listy incydentów według kryteriów
92    getIncidents: function({ status, type, severity, limit = 10 } = {}) {
93      let result = [...incidents]; // Kopia tablicy
94
95      // Filtrowanie według kryteriów
96      if (status) {
97        result = result.filter(inc => inc.status === status);
98      }
99
100      if (type) {
101        result = result.filter(inc => inc.type === type);
102      }
103
104      if (severity) {
105        result = result.filter(inc => inc.severity === severity);
106      }
107
108      // Sortowanie od najnowszych
109      result.sort((a, b) => new Date(b.reportedAt) - new Date(a.reportedAt));
110
111      // Limit wyników
112      return result.slice(0, limit);
113    }
114  };
115})();
116
117// Przykładowe użycie systemu
118const breakoutIncident = incidentManager.reportIncident({
119  type: "Ucieczka dinozaura",
120  location: "Zagroda Velociraptorów - Sektor C",
121  description: "Trzy velociraptory wydostały się z zagrody. Personel parku ewakuowany.",
122  severity: "Krytyczny",
123  reportedBy: "Robert Muldoon",
124  affectedAssets: ["VLR-02", "VLR-03", "VLR-04"],
125  notifyPersonnel: ["Dr. Grant", "John Hammond", "Ellie Sattler", "Ian Malcolm"]
126});
127
128console.log(breakoutIncident.message);
129// "Incydent #INC-1623844529123-456 został zarejestrowany"
130
131// Aktualizacja statusu incydentu
132const updateResult = incidentManager.updateIncidentStatus(
133  breakoutIncident.incidentId,
134  "W trakcie",
135  "Zespół SWAT"
136);
137console.log(updateResult.message);
138// "Status incydentu #INC-1623844529123-456 zaktualizowany na "W trakcie""
139
140// Pobranie informacji o incydencie
141const incidentDetails = incidentManager.getIncidentInfo(breakoutIncident.incidentId);
142console.log(incidentDetails);
143
144// Wyszukiwanie incydentów według kryteriów
145const criticalIncidents = incidentManager.getIncidents({
146  severity: "Krytyczny",
147  limit: 5
148});
149console.log(`Znaleziono ${criticalIncidents.length} krytycznych incydentów`);

Ten przykład demonstruje:

  1. Użycie destrukturyzacji obiektów do przyjmowania parametrów funkcji
  2. Zastosowanie parametrów domyślnych
  3. Użycie parametru rest do obsługi zmiennej liczby argumentów
  4. Użycie operatora spread do przekazywania argumentów
  5. Zaawansowane przetwarzanie i filtrowanie danych na podstawie parametrów

Podsumowanie

Funkcje w JavaScript oferują wiele potężnych mechanizmów pracy z parametrami i argumentami, które pozwalają tworzyć elastyczne, czytelne i łatwe w użyciu API:

  • Parametry domyślne upraszczają obsługę opcjonalnych argumentów
  • Parametr rest umożliwia funkcjom przyjmowanie zmiennej liczby argumentów
  • Operator spread pozwala na przekazywanie elementów tablicy jako oddzielnych argumentów
  • Destrukturyzacja obiektów ułatwia pracę z wieloma parametrami poprzez ich organizację w obiekty

Dzięki tym mechanizmom możemy tworzyć funkcje, które są elastyczne, ale jednocześnie proste w użyciu - co jest kluczowe w zarządzaniu skomplikowanymi systemami, takimi jak nasz wirtualny Park Jurajski.

Funkcjom strzałkowym, które wprowadzają bardziej zwięzłą składnię i specjalne zachowanie dotyczące kontekstu this, poświęcona jest osobna lekcja tego modułu.

Kod do tej lekcji: index.js
1// Parametry i argumenty funkcji - Park Jurajski
2console.log("Laboratorium Funkcji Parku Jurajskiego");
3console.log("Zarządzanie dinozaurami przez funkcje z parametrami\n");
4
5// ===========================================
6// 1. PODSTAWOWE FUNKCJE Z PARAMETRAMI
7// ===========================================
8console.log("=== 1. Funkcje z parametrami ===");
9
10// Funkcja z pojedynczym parametrem
11function feedDinosaur(dinoName) {
12  console.log(`Karmienie dinozaura: ${dinoName}`);
13}
14
15feedDinosaur("T-Rex");
16feedDinosaur("Velociraptor");
17
18// Funkcja z wieloma parametrami
19function addDinosaur(name, species, age, weight) {
20  console.log(`\nDodawanie nowego dinozaura do systemu:`);
21  console.log(`  Imię: ${name}`);
22  console.log(`  Gatunek: ${species}`);
23  console.log(`  Wiek: ${age} lat`);
24  console.log(`  Waga: ${weight} kg`);
25}
26
27addDinosaur("Blue", "Velociraptor", 5, 80);
28addDinosaur("Rexy", "Tyrannosaurus Rex", 8, 8000);
29
30// ===========================================
31// 2. PARAMETRY DOMYŚLNE (ES6)
32// ===========================================
33console.log("\n=== 2. Parametry domyślne ===");
34
35function scheduleFeeding(dinoName, foodType = "mięso", time = "12:00") {
36  console.log(`Zaplanowano karmienie ${dinoName}`);
37  console.log(`   Pokarm: ${foodType}, Godzina: ${time}`);
38}
39
40scheduleFeeding("Triceratops", "rośliny", "10:30");
41scheduleFeeding("Raptor"); // Użyje wartości domyślnych
42scheduleFeeding("Rex", undefined, "15:45"); // Pomiń środkowy parametr
43
44// Wyrażenia jako wartości domyślne
45function createPaddock(paddockNumber, capacity = paddockNumber * 2) {
46  console.log(`Tworzenie wybiegu #${paddockNumber} z pojemnością ${capacity}`);
47}
48
49createPaddock(5);
50createPaddock(3, 10);
51
52// ===========================================
53// 3. REST PARAMETERS (...args)
54// ===========================================
55console.log("\n=== 3. Rest parameters (...) ===");
56
57function feedMultipleDinosaurs(...dinoNames) {
58  console.log(`Karmienie ${dinoNames.length} dinozaurów:`);
59  dinoNames.forEach((name, index) => {
60    console.log(`  ${index + 1}. ${name}`);
61  });
62}
63
64feedMultipleDinosaurs("Rex", "Blue", "Charlie", "Delta");
65feedMultipleDinosaurs("Triceratops", "Stegosaurus");
66
67// Rest parameter z innymi parametrami
68function assignToTeam(teamLeader, ...teamMembers) {
69  console.log(`\nZespół kierowany przez: ${teamLeader}`);
70  console.log(`   Członkowie zespołu: ${teamMembers.join(", ")}`);
71}
72
73assignToTeam("Dr. Grant", "Ellie", "Ian", "Lex", "Tim");
74
75// ===========================================
76// 4. DESTRUCTURING PARAMETERS
77// ===========================================
78console.log("\n=== 4. Destructuring w parametrach ===");
79
80// Destructuring obiektów
81function displayDinosaurInfo({ name, species, age, weight, carnivore }) {
82  console.log(`\nInformacje o dinozaurze:`);
83  console.log(`  Imię: ${name}`);
84  console.log(`  Gatunek: ${species}`);
85  console.log(`  Wiek: ${age} lat`);
86  console.log(`  Waga: ${weight} kg`);
87  console.log(`  Typ: ${carnivore ? "Mięsożerca" : "Roślinożerca"}`);
88}
89
90const dino = {
91  name: "Blue",
92  species: "Velociraptor",
93  age: 5,
94  weight: 80,
95  carnivore: true
96};
97
98displayDinosaurInfo(dino);
99
100// Destructuring z wartościami domyślnymi
101function createEnclosure({ size = 100, type = "standard", security = "medium" } = {}) {
102  console.log(`\nTworzenie ogrodzenia:`);
103  console.log(`  Rozmiar: ${size} m²`);
104  console.log(`  Typ: ${type}`);
105  console.log(`  Zabezpieczenie: ${security}`);
106}
107
108createEnclosure({ size: 200, type: "high-security", security: "maximum" });
109createEnclosure({ size: 150 });
110createEnclosure(); // Wszystkie wartości domyślne
111
112// Destructuring tablic
113function assignPaddocks([first, second, third]) {
114  console.log(`\nPrzypisywanie wybiegów:`);
115  console.log(`  Wybieg A: ${first}`);
116  console.log(`  Wybieg B: ${second}`);
117  console.log(`  Wybieg C: ${third}`);
118}
119
120assignPaddocks(["T-Rex", "Triceratops", "Stegosaurus"]);
121
122// ===========================================
123// 5. RETURN VALUES
124// ===========================================
125console.log("\n=== 5. Zwracanie wartości ===");
126
127function calculateDangerLevel(species, age, aggression) {
128  let dangerScore = 0;
129
130  if (species === "Tyrannosaurus") dangerScore += 50;
131  else if (species === "Velociraptor") dangerScore += 40;
132  else if (species === "Triceratops") dangerScore += 20;
133  else dangerScore += 10;
134
135  dangerScore += age * 2;
136  dangerScore += aggression * 10;
137
138  let level = "Niskie";
139  if (dangerScore > 80) level = "Ekstremalne";
140  else if (dangerScore > 60) level = "Wysokie";
141  else if (dangerScore > 40) level = "Średnie";
142
143  return {
144    score: dangerScore,
145    level: level,
146    recommendation: dangerScore > 70 ? "Podwójne zabezpieczenie" : "Standardowe zabezpieczenie"
147  };
148}
149
150const trexDanger = calculateDangerLevel("Tyrannosaurus", 8, 9);
151console.log("Poziom zagrożenia T-Rex:", trexDanger);
152
153const triDanger = calculateDangerLevel("Triceratops", 5, 3);
154console.log("Poziom zagrożenia Triceratops:", triDanger);
155
156// ===========================================
157// 6. FUNKCJE ZWRACAJĄCE FUNKCJE
158// ===========================================
159console.log("\n=== 6. Funkcje wyższego rzędu ===");
160
161function createFeeder(foodType) {
162  return function(dinoName) {
163    console.log(`Karmienie ${dinoName} używając: ${foodType}`);
164  };
165}
166
167const meatFeeder = createFeeder("świeże mięso");
168const plantFeeder = createFeeder("rośliny");
169
170meatFeeder("T-Rex");
171meatFeeder("Velociraptor");
172plantFeeder("Triceratops");
173plantFeeder("Brachiosaurus");
174
175// ===========================================
176// 7. CALLBACK FUNCTIONS
177// ===========================================
178console.log("\n=== 7. Funkcje callback ===");
179
180function processDinosaurs(dinosaurs, callback) {
181  console.log("\nPrzetwarzanie listy dinozaurów:");
182  dinosaurs.forEach((dino, index) => {
183    callback(dino, index);
184  });
185}
186
187const dinoList = ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus"];
188
189processDinosaurs(dinoList, (dino, index) => {
190  console.log(`  ${index + 1}. ${dino} - Sprawdzenie zdrowia:`);
191});
192
193// ===========================================
194// 8. ARGUMENTS OBJECT (Legacy)
195// ===========================================
196console.log("\n=== 8. Obiekt arguments (starszy sposób) ===");
197
198function feedAll() {
199  console.log(`Karmienie ${arguments.length} dinozaurów:`);
200  for (let i = 0; i < arguments.length; i++) {
201    console.log(`  ${i + 1}. ${arguments[i]}`);
202  }
203}
204
205feedAll("Rex", "Blue", "Charlie", "Delta", "Echo");
206
207// ===========================================
208// 9. PRZYKŁAD KOMPLEKSOWY
209// ===========================================
210console.log("\n=== 9. System zarządzania parkiem - przykład kompleksowy ===");
211
212function managePark({
213  dinosaurs = [],
214  visitors = 0,
215  weather = "sunny",
216  securityLevel = "medium"
217} = {}) {
218  console.log("\nRAPORT PARKU JURAJSKIEGO");
219  console.log("================================");
220  console.log(`Dinozaury w parku: ${dinosaurs.length}`);
221  console.log(`Liczba odwiedzających: ${visitors}`);
222  console.log(`Pogoda: ${weather}`);
223  console.log(`Poziom bezpieczeństwa: ${securityLevel}`);
224
225  if (dinosaurs.length > 0) {
226    console.log("\nLista dinozaurów:");
227    dinosaurs.forEach((dino, idx) => {
228      console.log(`  ${idx + 1}. ${dino.name} (${dino.species})`);
229    });
230  }
231
232  const isOpen = weather === "sunny" && securityLevel !== "low";
233  console.log(`\nStatus parku: ${isOpen ? "OTWARTY" : "ZAMKNIĘTY"}`);
234
235  return {
236    isOperational: isOpen,
237    totalDinosaurs: dinosaurs.length,
238    capacity: visitors,
239    status: isOpen ? "Operational" : "Closed"
240  };
241}
242
243const parkStatus = managePark({
244  dinosaurs: [
245    { name: "Rexy", species: "T-Rex" },
246    { name: "Blue", species: "Velociraptor" },
247    { name: "Trike", species: "Triceratops" }
248  ],
249  visitors: 1500,
250  weather: "sunny",
251  securityLevel: "high"
252});
253
254console.log("\nPodsumowanie:", parkStatus);
255
256console.log("\nGratulacje! Opanowałeś parametry i argumenty funkcji!");

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Które użycie template literals jest poprawne?

  2. 2. Co zwróci typeof null w JavaScript?

  3. 3. Jak poprawnie utworzyć BigInt reprezentujący liczbę lat od wyginięcia dinozaurów?

  4. 4. Jaka jest główna cecha typu Symbol w JavaScript?

  5. 5. Które słowa kluczowe tworzą zmienne o zasięgu blokowym?

Zadania praktyczne w grze

  • Klikanie w kolejności

    Posortuj słowa kluczowe deklaracji zmiennych od najmniej do najbardziej restrykcyjnego:

  • Układanie w poziomie

    Ułóż elementy wywołania metody toUpperCase na stringu:

  • Klikanie w kolejności

    Uporządkuj cykl życia zmiennej w JavaScript:

Przydatne artykuły