Ajastid ja konteksti kaotus JavaScriptis

Ajastite kasutamisel sündmuste töötlejates ootavad meid probleemid konteksti kaotusega. Vaatame seda näite varal.

Oletame, et meil on sisendväli:

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

Oletame, et klõpsates sellel sisendväljal käivitub anonüümne funktsioon ja selle funktsiooni sees käivitub ajasti, mis iga sekund väljastab midagi konsooli:

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

elem.addEventListener('click', function() {
  setInterval(function() {
    console.log('!!!'); // väljastame midagi konsooli
  }, 1000);
});

Siiani kõik töötab õigesti. Kuid nüüd oletame, et me tahame konsooli väljastada value meie sisendväljalt - meid ootab üllatus: konsooli väljub undefined:

javascriptelem.addEventListener('click', function() {
  setInterval(function() {
    console.log(this.value); // väljub undefined
  }, 1000);
});

Asi on selles, et meil tekib funktsioon funktsiooni sees: on väline anonüümne funktsioon, mida kutsutakse välja klõpsu peale ja sisemine anonüümne funktsioon, mida käivitab ajasti. Välises funktsioonis viitab this sisendväljale, kuid sisemises - mitte. Tekib konteksti kaotus.

Miks väljub undefined, mitte ei teki veateadet konsooli, nagu see oli eelmistes õppetükides? Sellepärast, et this funktsiooni sees, mida kutsutakse välja läbi setInterval, viitab window-ile.

See tähendab, et me püüame lugeda omadust value objektilt window, niimoodi: window.value, kuid sellist omadust seal pole, ja me saame undefined (mitte vea).

Parandame probleemi self kasutuselevõtuga:

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

Oletame, et on antud selline kood:

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

Koodi autor soovis, et nuppu vajutades suureneks selle nupu väärtus iga sekund 1 võrra. Kuid nuppu vajutades ei juhtu aga midagi. Parandage koodi autori viga. Kirjutage tekst, milles annate selgituse koodi autorile, miks tekkis tema viga.