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

Słowo kluczowe this w JavaScript

Witaj ponownie w Parku Jurajskim! Dzisiaj zagłębimy się w jedno z najbardziej intrygujących i czasami mylących zagadnień w JavaScript: słowo kluczowe

this
. Zrozumienie
this
jest kluczowe dla efektywnego programowania obiektowego w JavaScript i tworzenia złożonych systemów, takich jak nasz system zarządzania parkiem.

Czym jest this?

Słowo kluczowe

this
w JavaScript odnosi się do obiektu, w którego kontekście wykonywana jest funkcja. Można o nim myśleć jak o "aktualnym miejscu pracy" - podobnie jak pracownik Parku Jurajskiego może pracować w różnych lokalizacjach (np. laboratorium, zagroda T-Rexa, centrum kontroli), tak samo funkcja może być wykonywana w różnych kontekstach.

Wartość

this
nie jest ustalana w momencie definiowania funkcji, ale w momencie jej wywołania, co może powodować pewne zamieszanie. Wartość
this
zależy od tego, jak funkcja jest wywoływana:

  1. W kontekście globalnym
  2. Jako metoda obiektu
  3. Jako konstruktor
  4. Za pomocą metod
    call()
    ,
    apply()
    lub
    bind()
  5. W funkcjach strzałkowych

Przyjrzyjmy się każdemu z tych przypadków.

1. This w kontekście globalnym

Gdy

this
jest używane w globalnym zasięgu (poza jakąkolwiek funkcją) lub w zwykłej funkcji (niewywołanej jako metoda obiektu), odnosi się do obiektu globalnego. W przeglądarce jest to obiekt
window
, a w Node.js -
global
.

1// W globalnym zasięgu
2console.log(this); // obiekt window (w przeglądarce) lub global (w Node.js)
3
4// W zwykłej funkcji
5function checkGlobalThis() {
6  console.log(this); // również obiekt window/global
7}
8
9checkGlobalThis();

W trybie ścisłym (

"use strict";
),
this
w zwykłej funkcji będzie
undefined
zamiast obiektu globalnego, co pomaga uniknąć przypadkowego tworzenia globalnych zmiennych.

1"use strict";
2
3function strictThis() {
4  console.log(this); // undefined
5}
6
7strictThis();

2. This jako metoda obiektu

Gdy funkcja jest wywoływana jako metoda obiektu,

this
odnosi się do tego obiektu. Jest to jeden z najczęstszych i najbardziej intuicyjnych sposobów użycia
this
w JavaScript.

1// Obiekt reprezentujący dinozaura
2const velociraptor = {
3  name: "Blue",
4  species: "Velociraptor",
5  age: 5,
6
7  // Metoda wykorzystująca this
8  describe: function() {
9    console.log(`Ten ${this.species} ma na imię ${this.name} i ma ${this.age} lat.`);
10  },
11
12  // Metoda zmieniająca dane dinozaura
13  ageDinosaur: function(years) {
14    this.age += years;
15    console.log(`${this.name} ma teraz ${this.age} lat.`);
16  }
17};
18
19// Wywołanie metod
20velociraptor.describe(); // "Ten Velociraptor ma na imię Blue i ma 5 lat."
21velociraptor.ageDinosaur(2); // "Blue ma teraz 7 lat."

W powyższym przykładzie,

this
wewnątrz metod
describe
i
ageDinosaur
odnosi się do obiektu
velociraptor
, dzięki czemu metody mają dostęp do jego właściwości.

Potencjalna pułapka: utrata kontekstu

Jednak trzeba uważać - kontekst

this
może zostać utracony, jeśli metodę przypiszemy do innej zmiennej i wywołamy ją jako zwykłą funkcję:

1const velociraptor = {
2  name: "Blue",
3  describe: function() {
4    console.log(`Cześć, jestem ${this.name}!`);
5  }
6};
7
8// Wywołanie jako metoda - this odnosi się do velociraptor
9velociraptor.describe(); // "Cześć, jestem Blue!"
10
11// Ale gdy przypiszemy metodę do zmiennej...
12const describeDino = velociraptor.describe;
13
14// ...i wywołamy jako zwykłą funkcję
15describeDino(); // "Cześć, jestem undefined!"
16// (lub "Cześć, jestem !", jeśli istnieje globalna zmienna name)

To częsty problem przy przekazywaniu metod jako funkcji zwrotnych (callbacks):

1const trex = {
2  name: "Rex",
3  roar: function() {
4    console.log(`${this.name} ryczy głośno!`);
5  }
6};
7
8// Bezpośrednie wywołanie działa
9trex.roar(); // "Rex ryczy głośno!"
10
11// Ale jako callback po 1 sekundzie...
12setTimeout(trex.roar, 1000); // "undefined ryczy głośno!"
13
14// Rozwiązanie (jednym ze sposobów) jest użycie funkcji strzałkowej lub bind():
15setTimeout(() => trex.roar(), 1000); // "Rex ryczy głośno!"
16setTimeout(trex.roar.bind(trex), 1000); // "Rex ryczy głośno!"

3. This w konstruktorach

Gdy funkcja jest wywoływana z operatorem

new
(jako konstruktor),
this
odnosi się do nowo tworzonego obiektu. Jest to fundamentalny mechanizm tworzenia instancji obiektów w JavaScript.

1// Funkcja konstruktora dla dinozaurów
2function Dinosaur(name, species, age) {
3  // 'this' odnosi się do nowo tworzonego obiektu
4  this.name = name;
5  this.species = species;
6  this.age = age;
7
8  this.describe = function() {
9    console.log(`${this.name} to ${this.species} w wieku ${this.age} lat.`);
10  };
11}
12
13// Tworzenie nowych instancji
14const blue = new Dinosaur("Blue", "Velociraptor", 5);
15const rex = new Dinosaur("Rex", "Tyrannosaurus", 8);
16
17blue.describe(); // "Blue to Velociraptor w wieku 5 lat."
18rex.describe(); // "Rex to Tyrannosaurus w wieku 8 lat."
19
20// Zmodyfikujmy wiek Blue
21blue.age = 6;
22blue.describe(); // "Blue to Velociraptor w wieku 6 lat."

W nowoczesnym JavaScript (ES6+) zamiast funkcji konstruktora często używamy klas, które zapewniają bardziej przejrzystą składnię do robienia tego samego:

1// Klasa ES6 dla dinozaurów
2class Dinosaur {
3  constructor(name, species, age) {
4    this.name = name;
5    this.species = species;
6    this.age = age;
7  }
8
9  // Metody są automatycznie dodawane do prototypu
10  describe() {
11    console.log(`${this.name} to ${this.species} w wieku ${this.age} lat.`);
12  }
13
14  // Metoda zmieniająca wiek
15  growOlder(years = 1) {
16    this.age += years;
17    console.log(`${this.name} ma teraz ${this.age} lat.`);
18  }
19}
20
21// Tworzenie instancji
22const trixie = new Dinosaur("Trixie", "Triceratops", 7);
23trixie.describe(); // "Trixie to Triceratops w wieku 7 lat."
24trixie.growOlder(3); // "Trixie ma teraz 10 lat."

4. Kontrolowanie this: call(), apply() i bind()

JavaScript oferuje trzy metody, które pozwalają jawnie kontrolować wartość

this
podczas wywoływania funkcji:

call()

Metoda

call()
wywołuje funkcję z podanym wartością
this
i argumentami przekazanymi pojedynczo:

1function examineSpecimen(testType, labNumber) {
2  console.log(`Badanie ${this.species} o imieniu ${this.name}...`);
3  console.log(`Typ testu: ${testType}, Laboratorium: ${labNumber}`);
4}
5
6const specimen = {
7  name: "Echo",
8  species: "Velociraptor",
9  age: 3
10};
11
12// Wywołanie funkcji z 'this' ustawionym na specimen
13examineSpecimen.call(specimen, "DNA", "Lab-A");
14// "Badanie Velociraptor o imieniu Echo..."
15// "Typ testu: DNA, Laboratorium: Lab-A"

apply()

Metoda

apply()
działa podobnie do
call()
, ale argumenty są przekazywane jako tablica:

1// Ta sama funkcja
2function examineSpecimen(testType, labNumber) {
3  console.log(`Badanie ${this.species} o imieniu ${this.name}...`);
4  console.log(`Typ testu: ${testType}, Laboratorium: ${labNumber}`);
5}
6
7// Wywołanie z argumentami w tablicy
8examineSpecimen.apply(specimen, ["Behawioralny", "Lab-B"]);
9// "Badanie Velociraptor o imieniu Echo..."
10// "Typ testu: Behawioralny, Laboratorium: Lab-B"

bind()

Metoda

bind()
tworzy nową funkcję z trwale przypisaną wartością
this
:

1const dinosaur = {
2  name: "Delta",
3  species: "Velociraptor"
4};
5
6function makeSound(sound) {
7  console.log(`${this.name} wydaje dźwięk: ${sound}!`);
8}
9
10// Tworzenie nowej funkcji z 'this' przypisanym do dinosaur
11const dinosaurSound = makeSound.bind(dinosaur);
12
13// Teraz możemy wywoływać tę funkcję wielokrotnie
14dinosaurSound("Warczenie"); // "Delta wydaje dźwięk: Warczenie!"
15dinosaurSound("Syczenie"); // "Delta wydaje dźwięk: Syczenie!"
16
17// Możemy też powiązać argumenty
18const deltaRoar = makeSound.bind(dinosaur, "ROAR");
19deltaRoar(); // "Delta wydaje dźwięk: ROAR!"

Praktyczny przykład: Tworzenie systemu śledzenia dinozaurów

Poniższy przykład pokazuje, jak można wykorzystać różne metody kontrolowania

this
do tworzenia elastycznego systemu monitorowania:

1const dinoMonitoringSystem = {
2  activeDinosaurs: [],
3
4  // Rejestracja nowego dinozaura
5  registerDinosaur: function(dinosaur) {
6    this.activeDinosaurs.push(dinosaur);
7    console.log(`Zarejestrowano nowego dinozaura: ${dinosaur.name} (${dinosaur.species})`);
8  },
9
10  // Wyszukiwanie dinozaura po imieniu
11  findDinosaurByName: function(name) {
12    return this.activeDinosaurs.find(dino => dino.name === name);
13  },
14
15  // Uruchomienie procedury alertu
16  triggerAlert: function(message) {
17    console.log(`ALERT SYSTEMOWY: ${message}`);
18
19    // Powiadamianie o wszystkich aktywnych dinozaurach
20    this.activeDinosaurs.forEach(function(dino) {
21      console.log(`- ${dino.name} (${dino.species}) w sektorze ${dino.sector}`);
22    });
23  }
24};
25
26// Klasa Dinosaur z metodą przemieszczania
27class Dinosaur {
28  constructor(name, species, sector) {
29    this.name = name;
30    this.species = species;
31    this.sector = sector;
32    this.status = "spokojny";
33  }
34
35  move(newSector, monitoringSystem) {
36    // Możemy przekazać monitoringSystem jako parametr
37    console.log(`${this.name} przemieszcza się z sektora ${this.sector} do sektora ${newSector}`);
38    this.sector = newSector;
39
40    // Lub użyć call() do wywołania metody z właściwym kontekstem
41    const alertMessage = `Dinozaur ${this.name} wszedł do sektora ${newSector}!`;
42    monitoringSystem.triggerAlert.call(monitoringSystem, alertMessage);
43  }
44
45  // Metoda zmieniająca status dinozaura
46  updateStatus(newStatus) {
47    this.status = newStatus;
48    console.log(`Status dinozaura ${this.name} zmieniony na: ${this.status}`);
49    return this;
50  }
51}
52
53// Inicjalizacja systemu i dinozaurów
54const rex = new Dinosaur("Rex", "Tyrannosaurus", "A");
55const blue = new Dinosaur("Blue", "Velociraptor", "B");
56const delta = new Dinosaur("Delta", "Velociraptor", "B");
57
58// Rejestracja dinozaurów w systemie
59dinoMonitoringSystem.registerDinosaur(rex);
60dinoMonitoringSystem.registerDinosaur(blue);
61dinoMonitoringSystem.registerDinosaur(delta);
62
63// Przemieszczenie dinozaura
64blue.move("C", dinoMonitoringSystem);
65
66// Łańcuchowanie metod (dzięki return this)
67rex.updateStatus("pobudzony").updateStatus("agresywny");
68
69// Wykorzystanie bind() do tworzenia funkcji z predefiniowanym 'this'
70const checkRexStatus = function() {
71  console.log(`Status T-Rexa: ${this.status}`);
72};
73
74const boundCheckStatus = checkRexStatus.bind(rex);
75boundCheckStatus(); // "Status T-Rexa: agresywny"

5. This w funkcjach strzałkowych

Funkcje strzałkowe, wprowadzone w ES6, obsługują

this
inaczej niż tradycyjne funkcje. Nie mają własnego
this
, zamiast tego "dziedziczą"
this
z otaczającego zakresu leksykalnego.

1const parkSystem = {
2  name: "Jurassic Park",
3  dinosaurs: ["T-Rex", "Velociraptor", "Triceratops"],
4
5  // Metoda wykorzystująca funkcję strzałkową
6  listDinosaurs: function() {
7    console.log(`${this.name} zawiera następujące dinozaury:`);
8
9    // Funkcja strzałkowa zachowuje 'this' z zakresu listDinosaurs
10    this.dinosaurs.forEach(dino => {
11      console.log(`- ${dino} w parku ${this.name}`);
12    });
13
14    // Dla porównania - tradycyjna funkcja straciłaby kontekst 'this'
15    /*
16    this.dinosaurs.forEach(function(dino) {
17      // 'this' odnosi się do globalnego obiektu lub jest undefined w trybie ścisłym
18      console.log(`- ${dino} w parku ${this.name}`); // this.name będzie undefined
19    });
20    */
21  }
22};
23
24parkSystem.listDinosaurs();
25// "Jurassic Park zawiera następujące dinozaury:"
26// "- T-Rex w parku Jurassic Park"
27// "- Velociraptor w parku Jurassic Park"
28// "- Triceratops w parku Jurassic Park"

Funkcje strzałkowe są szczególnie przydatne w przypadkach, gdy chcemy zachować kontekst

this
w funkcjach zagnieżdżonych, funkcjach zwrotnych (callbacks) lub programowaniu asynchronicznym.

Praktyczny przykład: System monitorowania z czasomierzami

1class DinosaurMonitor {
2  constructor(name, species) {
3    this.name = name;
4    this.species = species;
5    this.status = "Normalny";
6    this.lastUpdated = new Date();
7    this.checkInterval = null;
8  }
9
10  // Rozpoczęcie monitorowania z regularnym sprawdzaniem statusu
11  startMonitoring() {
12    console.log(`Rozpoczęcie monitorowania dinozaura: ${this.name}`);
13
14    // Funkcja strzałkowa zachowuje kontekst 'this'
15    this.checkInterval = setInterval(() => {
16      this.checkStatus();
17    }, 5000);
18
19    // Gdybyśmy użyli zwykłej funkcji, stracilibyśmy kontekst:
20    /*
21    this.checkInterval = setInterval(function() {
22      // 'this' odnosi się tutaj do globalnego obiektu, nie do instancji DinosaurMonitor
23      this.checkStatus(); // Błąd: this.checkStatus is not a function
24    }, 5000);
25    */
26  }
27
28  // Sprawdzenie statusu dinozaura
29  checkStatus() {
30    const now = new Date();
31    const timeSinceLastUpdate = (now - this.lastUpdated) / 1000; // w sekundach
32
33    console.log(`Sprawdzanie statusu dinozaura ${this.name} (${this.species})...`);
34    console.log(`Ostatnia aktualizacja: ${timeSinceLastUpdate.toFixed(1)} sekund temu`);
35    console.log(`Status: ${this.status}`);
36
37    this.lastUpdated = now;
38
39    // Symulacja zmiany statusu (w rzeczywistym systemie byłyby tu dane z czujników)
40    if (Math.random() < 0.3) {
41      const possibleStatuses = ["Normalny", "Pobudzony", "Odpoczywający", "Żerujący", "Agresywny"];
42      this.status = possibleStatuses[Math.floor(Math.random() * possibleStatuses.length)];
43      console.log(`Nowy status: ${this.status}`);
44    }
45  }
46
47  // Zatrzymanie monitorowania
48  stopMonitoring() {
49    if (this.checkInterval) {
50      clearInterval(this.checkInterval);
51      this.checkInterval = null;
52      console.log(`Zatrzymano monitorowanie dinozaura: ${this.name}`);
53    }
54  }
55}
56
57// Utworzenie i uruchomienie monitora
58const blueMonitor = new DinosaurMonitor("Blue", "Velociraptor");
59blueMonitor.startMonitoring();
60
61// Zatrzymanie monitora po 20 sekundach
62setTimeout(() => {
63  blueMonitor.stopMonitoring();
64}, 20000);

Typowe pułapki związane z this

Słowo kluczowe

this
może być źródłem wielu błędów w JavaScript. Oto kilka typowych pułapek i jak ich unikać:

1. Utrata kontekstu w funkcjach zagnieżdżonych

1const dinosaur = {
2  name: "Rex",
3  behaviors: ["polowanie", "odpoczynek", "bieganie"],
4
5  logBehaviors: function() {
6    // 'this' odnosi się tutaj do 'dinosaur'
7    console.log(`Dinozaur ${this.name} wykazuje następujące zachowania:`);
8
9    // Problem: 'this' w funkcji forEach odnosi się do globalnego obiektu
10    this.behaviors.forEach(function(behavior) {
11      // 'this.name' jest undefined
12      console.log(`- ${this.name} lubi ${behavior}`);
13    });
14  }
15};
16
17dinosaur.logBehaviors();
18// "Dinozaur Rex wykazuje następujące zachowania:"
19// "- undefined lubi polowanie"
20// "- undefined lubi odpoczynek"
21// "- undefined lubi bieganie"

Rozwiązania:

  1. Użyj funkcji strzałkowej:
1const dinosaur = {
2  name: "Rex",
3  behaviors: ["polowanie", "odpoczynek", "bieganie"],
4
5  logBehaviors: function() {
6    console.log(`Dinozaur ${this.name} wykazuje następujące zachowania:`);
7
8    // Funkcja strzałkowa zachowuje 'this' z otaczającego zakresu
9    this.behaviors.forEach(behavior => {
10      console.log(`- ${this.name} lubi ${behavior}`);
11    });
12  }
13};
  1. Zachowaj referencję do
    this
    w zmiennej:
1const dinosaur = {
2  name: "Rex",
3  behaviors: ["polowanie", "odpoczynek", "bieganie"],
4
5  logBehaviors: function() {
6    console.log(`Dinozaur ${this.name} wykazuje następujące zachowania:`);
7
8    // Zachowanie referencji do 'this' w zmiennej 'self' lub 'that'
9    const self = this;
10    this.behaviors.forEach(function(behavior) {
11      console.log(`- ${self.name} lubi ${behavior}`);
12    });
13  }
14};
  1. Użyj metody
    bind()
    :
1const dinosaur = {
2  name: "Rex",
3  behaviors: ["polowanie", "odpoczynek", "bieganie"],
4
5  logBehaviors: function() {
6    console.log(`Dinozaur ${this.name} wykazuje następujące zachowania:`);
7
8    // Użycie bind() do powiązania 'this'
9    this.behaviors.forEach(function(behavior) {
10      console.log(`- ${this.name} lubi ${behavior}`);
11    }.bind(this));
12  }
13};

2. Metody jako callbacks

Gdy metoda obiektu jest przekazywana jako callback, traci swój kontekst

this
:

1class DinosaurTracker {
2  constructor(name) {
3    this.name = name;
4    this.tracked = false;
5  }
6
7  startTracking() {
8    this.tracked = true;
9    console.log(`Rozpoczęto śledzenie dinozaura ${this.name}`);
10  }
11}
12
13const blueTracker = new DinosaurTracker("Blue");
14
15// Działa poprawnie
16blueTracker.startTracking();
17
18// Nie działa - 'this' nie odnosi się do blueTracker
19setTimeout(blueTracker.startTracking, 1000); // "Rozpoczęto śledzenie dinozaura undefined"

Rozwiązania:

  1. Użyj funkcji strzałkowej:
1setTimeout(() => blueTracker.startTracking(), 1000);
  1. Użyj
    bind()
    :
1setTimeout(blueTracker.startTracking.bind(blueTracker), 1000);

Zaawansowany przykład: System zarządzania parkiem

Poniżej znajduje się bardziej złożony przykład systemu zarządzania Parkiem Jurajskim, który wykorzystuje różne aspekty słowa kluczowego

this
:

1// Główny system zarządzania parkiem
2const parkManagementSystem = {
3  parkName: "Jurassic Park",
4  status: "operational",
5  securityLevel: "normal",
6
7  // Podsystemy parku
8  subsystems: {
9    power: { status: "online", output: "100%" },
10    security: { status: "active", fences: "operational" },
11    visitorCenter: { status: "open", visitors: 120 }
12  },
13
14  // Metoda inicjująca system
15  initialize: function() {
16    console.log(`Inicjalizacja systemu zarządzania parkiem: ${this.parkName}`);
17
18    // Sprawdzenie wszystkich podsystemów
19    this.checkAllSubsystems();
20
21    // Ustawienie regularnego monitorowania
22    this.startMonitoring();
23
24    return this;
25  },
26
27  // Sprawdzenie stanu podsystemów
28  checkAllSubsystems: function() {
29    console.log("Sprawdzanie statusu wszystkich podsystemów...");
30
31    // Użycie Object.entries i funkcji strzałkowej dla zachowania kontekstu 'this'
32    Object.entries(this.subsystems).forEach(([name, system]) => {
33      console.log(`- Podsystem ${name}: ${system.status}`);
34
35      // Wywołanie specyficznych sprawdzeń dla każdego podsystemu
36      this[`check${name.charAt(0).toUpperCase() + name.slice(1)}`]();
37    });
38  },
39
40  // Specyficzne metody sprawdzające dla każdego podsystemu
41  checkPower: function() {
42    const powerSystem = this.subsystems.power;
43    console.log(`  Sprawdzanie zasilania: ${powerSystem.status}, Moc: ${powerSystem.output}`);
44  },
45
46  checkSecurity: function() {
47    const securitySystem = this.subsystems.security;
48    console.log(`  Sprawdzanie zabezpieczeń: ${securitySystem.status}, Ogrodzenia: ${securitySystem.fences}`);
49  },
50
51  checkVisitorCenter: function() {
52    const visitorSystem = this.subsystems.visitorCenter;
53    console.log(`  Sprawdzanie centrum dla zwiedzających: ${visitorSystem.status}, Odwiedzający: ${visitorSystem.visitors}`);
54  },
55
56  // Rozpoczęcie regularnego monitorowania
57  startMonitoring: function() {
58    console.log("Rozpoczęcie regularnego monitorowania parku...");
59
60    // Funkcja strzałkowa dla zachowania kontekstu 'this'
61    this.monitoringInterval = setInterval(() => {
62      this.checkSecurityStatus();
63    }, 10000);
64
65    // Symulacja wywołania metody po 5 sekundach
66    setTimeout(() => this.simulateSecurityAlert(), 5000);
67  },
68
69  // Sprawdzenie statusu bezpieczeństwa
70  checkSecurityStatus: function() {
71    console.log(`[MONITOR] Status parku: ${this.status}, Poziom bezpieczeństwa: ${this.securityLevel}`);
72  },
73
74  // Symulacja alertu bezpieczeństwa
75  simulateSecurityAlert: function() {
76    console.log("SYMULACJA: Wykryto naruszenie zabezpieczeń w sektorze B!");
77
78    // Zmiana statusu parku i poziomu bezpieczeństwa
79    this.status = "alert";
80    this.securityLevel = "high";
81    console.log(`Status parku zmieniony na: ${this.status}`);
82    console.log(`Poziom bezpieczeństwa podniesiony do: ${this.securityLevel}`);
83
84    // Bezpośrednie sprawdzenie statusu
85    this.checkSecurityStatus();
86
87    // Utworzenie zespołu reagowania kryzysowego używając konstruktora
88    const responseTeam = new EmergencyResponseTeam(this);
89
90    // Przekazanie metody jako callback z zachowaniem kontekstu
91    responseTeam.respondToAlert(this.resolveSecurityAlert.bind(this));
92  },
93
94  // Rozwiązanie alertu bezpieczeństwa
95  resolveSecurityAlert: function(report) {
96    console.log(`Otrzymano raport od zespołu reagowania: ${report}`);
97
98    // Przywrócenie normalnego statusu
99    this.status = "operational";
100    this.securityLevel = "normal";
101    console.log("Alert bezpieczeństwa rozwiązany.");
102    console.log(`Status parku przywrócony do: ${this.status}`);
103
104    // Sprawdzenie aktualnego statusu
105    this.checkSecurityStatus();
106  },
107
108  // Zatrzymanie monitorowania
109  stopMonitoring: function() {
110    if (this.monitoringInterval) {
111      clearInterval(this.monitoringInterval);
112      console.log("Monitorowanie parku zatrzymane.");
113    }
114  }
115};
116
117// Konstruktor dla zespołu reagowania kryzysowego
118function EmergencyResponseTeam(park) {
119  // 'this' odnosi się do nowego obiektu
120  this.teamName = "Zespół Reagowania Kryzysowego";
121  this.members = ["Owen Grady", "Claire Dearing", "Dr. Wu"];
122  this.assignedPark = park;
123
124  this.respondToAlert = function(callback) {
125    console.log(`${this.teamName} reaguje na alert w parku: ${this.assignedPark.parkName}`);
126
127    // Symulacja czasu reakcji
128    setTimeout(() => {
129      console.log(`${this.teamName} zabezpieczył obszar i przywrócił ogrodzenia.`);
130
131      // Wywołanie callbacka z raportem
132      if (typeof callback === 'function') {
133        callback("Zagrożenie zneutralizowane, ogrodzenia naprawione");
134      }
135    }, 3000);
136  };
137}
138
139// Inicjalizacja i uruchomienie systemu
140parkManagementSystem.initialize();
141
142// Zatrzymanie systemu po 20 sekundach
143setTimeout(() => {
144  parkManagementSystem.stopMonitoring();
145}, 20000);

Podsumowanie i najlepsze praktyki

Słowo kluczowe

this
jest potężnym narzędziem w JavaScript, ale wymaga zrozumienia, jak się zachowuje w różnych kontekstach:

  1. W globalnym kontekście:

    this
    odnosi się do obiektu globalnego (
    window
    lub
    global
    ).

  2. W metodzie obiektu:

    this
    odnosi się do obiektu, który wywołał metodę.

  3. W konstruktorze:

    this
    odnosi się do nowo tworzonego obiektu.

  4. W funkcjach strzałkowych:

    this
    jest dziedziczone z otaczającego zakresu leksykalnego.

  5. Przy użyciu call/apply/bind:

    this
    jest jawnie określone przez programistę.

Najlepsze praktyki:

  1. Używaj funkcji strzałkowych dla funkcji zwrotnych (callbacks) i funkcji zagnieżdżonych, aby zachować kontekst

    this
    .

  2. Używaj metod

    call()
    ,
    apply()
    lub
    bind()
    , gdy potrzebujesz jawnie kontrolować wartość
    this
    .

  3. Unikaj tworzenia metod w konstruktorach, zamiast tego dodawaj je do prototypu, aby uniknąć duplikacji kodu.

  4. Pamiętaj, że

    this
    jest ustalane podczas wywoływania funkcji, a nie podczas jej definiowania.

  5. Używaj klas ES6 zamiast tradycyjnych konstruktorów, aby uzyskać bardziej przejrzysty kod.

W następnym module zajmiemy się głębiej tablicami w JavaScript, które są kluczowym elementem zarządzania kolekcjami danych w naszym Parku Jurajskim.

Przejdź do CodeWorlds