Időzítők és a kontextus elvesztése a JavaScriptben

Az időzítők eseménykezelőkben való használatakor kontextusvesztési problémák leselkednek ránk. Nézzük meg ezt egy példán keresztül.

Tegyük fel, hogy van egy bemeneti mezőnk:

html<input id="elem" value="text">

Tegyük fel, hogy egy kattintásra ez a bemeneti mező egy anonim függvényt aktivál, és ezen függvényen belül elindul egy időzítő, amely másodpercenként kiír valamit a konzolra:

javascriptlet elem = document.querySelector('#elem');

elem.addEventListener('click', function() {
  setInterval(function() {
    console.log('!!!'); // kiírunk valamit a konzolra
  }, 1000);
});

Eddig minden helyesen működik. De tegyük fel most, hogy a bemeneti mező value értékét szeretnénk kiírni a konzolra - egy meglepetés ériz ránk: a konzolba undefined fog kiíródni:

javascriptelem.addEventListener('click', function() {
  setInterval(function() {
    console.log(this.value); // undefined fog kiíródni
  }, 1000);
});

Az egész azon múlik, hogy egy függvényt kapunk egy függvényben: van egy külső anonim függvény, amely kattintásra hívódik meg, és egy belső anonim függvény, amelyet az időzítő indít el. A külső függvényben a this a bemeneti mezőre mutat, de a belsőben - nem. Kontextusvesztés következik be.

Miért jelenik meg undefined, és nem jelenik meg egy hiba a konzolban, mint az előző leckékben? Mert a this azon függvényen belül, amelyet setInterval-lel hívunk meg, a window objektumra mutat.

Ez azt jelenti, hogy megpróbáljuk elolvasni a value tulajdonságot a window objektumtól, így: window.value, de ilyen tulajdonság nincs benne, és így undefined-et kapunk (nem hibát).

Javítsuk a problémát egy self változó bevezetésével:

javascriptelem.addEventListener('click', function() {
  let self = this;
  
  setInterval(function() {
    console.log(self.value);
  }, 1000);
});
Задание 1

Tegyük fel, hogy a következő kód adott:

html<input type="button" id="elem" value="1">
javascriptlet elem = document.querySelector('#elem');

elem.addEventListener('click', function() {
  setInterval(function() {
    this.value = Number(elem.value) + 1;
  }, 1000);
});

A kód szerzője azt szerette volna, hogy a gombra kattintáskor a gomb értéke másodpercenként 1-gyel növekedjen. Azonban a gombra kattintáskor egyáltalán semmi sem történik. Javítsa ki a kód szerzőjének hibáját. Írjon egy szöveget, amelyben magyarázatot ad a kód szerzőjének, hogy miért következett be a hibája.