Č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:

html<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:

javascriptlet 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:

javascriptelem.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:

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

Nech je daný takýto kód:

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);
});

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.