Časovače a ztráta kontextu v JavaScriptu

Při použití časovačů v obslužných funkcích událostí na nás číhají problémy se ztrátou kontextu. Podívejme se na příklad.

Předpokládejme, že máme vstupní pole:

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

Předpokládejme, že po kliknutí na toto vstupní pole se spustí anonymní funkce a uvnitř této funkce se spustí časovač, který každou sekundu vypíše něco do konzole:

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

elem.addEventListener('click', function() {
  setInterval(function() {
    console.log('!!!'); // něco vypíšeme do konzole
  }, 1000);
});

Zatím vše funguje správně. Ale nyní předpokládejme, že chceme do konzole vypsat value našeho vstupního pole - čeká nás překvapení: do konzole se bude vypisovat undefined:

javascriptelem.addEventListener('click', function() {
  setInterval(function() {
    console.log(this.value); // bude se vypisovat undefined
  }, 1000);
});

Jde o to, že máme funkci ve funkci: existuje vnější anonymní funkce, která je volána po kliknutí, a vnitřní anonymní funkce, kterou spouští časovač. Ve vnější funkci this ukazuje na vstupní pole, ale ve vnitřní - ne. Dochází ke ztrátě kontextu.

Proč se vypisuje undefined, a neobjeví se chyba v konzoli, jako tomu bylo v předchozích lekcích? Protože this uvnitř funkce, volané přes setInterval, ukazuje na window.

To znamená, že se snažíme přečíst vlastnost value u objektu window, takto: window.value, a taková vlastnost v něm není, a dostáváme undefined (ne chybu).

Problém opravíme zavedením self:

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

Předpokládejme, že je dán takový 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 chtěl, aby se po stisknutí tlačítka hodnota tohoto tlačítka každou sekundu zvyšovala o 1. Avšak po stisknutí tlačítka se nic neděje. Opravte chybu autora kódu. Napište text, ve kterém poskytnete autorovi kódu vysvětlení, proč k jeho chybě došlo.