Časovače a strata kontextu v JavaScripte
Pri použití časovačov v obslužných funkciách udalostí nás čakajú problémy so stratou kontextu. Pozrime sa na príklad.
Majme vstupné pole:
<input id="elem" value="text">
Nech pri kliknutí na toto vstupné pole sa spustí anonymná funkcia a vnútri tejto funkcie sa spustí časovač, ktorý každú sekundu niečo vypíše do konzoly:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // niečo vypíšeme do konzoly
}, 1000);
});
Zatiaľ všetko funguje správne. Ale nech teraz
chceme vypísať do konzoly value
nášho vstupného poľa - čaká nás prekvapenie: do konzoly
sa bude vypisovať undefined:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // bude sa vypisovať undefined
}, 1000);
});
Celé je to o tom, že máme funkciu
vo funkcii: existuje vonkajšia anonymná funkcia,
ktorá sa volá pri kliknutí a vnútorná
anonymná funkcia, ktorú spúšťa časovač.
Vo vonkajšej funkcii this ukazuje
na vstupné pole, ale vo vnútornej - nie. Ide o
stratu kontextu.
Prečo sa vypíše undefined a nevypadne
chyba do konzoly, ako to bolo v predchádzajúcich
lekciách? Pretože this vo funkcii,
volanej prostredníctvom setInterval, ukazuje
na window.
To znamená, že sa snažíme prečítať vlastnosť
value objektu window, takto: window.value,
a taká vlastnosť v ňom nie je, a dostaneme
undefined (nie chybu).
Opravme problém zavedením self:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Nech je daný takýto kód:
<input type="button" id="elem" value="1">
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
this.value = Number(elem.value) + 1;
}, 1000);
});
Autor kódu chcel, aby po stlačení tlačidla,
hodnota tohto tlačidla sa každú sekundu zvyšovala
o 1. Avšak, po stlačení tlačidla
sa vôbec nič nedeje. Opravte chybu
autora kódu. Napíšte text, v ktorom
poskytnete vysvetlenie autorovi kódu, prečo nastala
jeho chyba.