Таймери и загуба на контекст в JavaScript

При използване на таймери в манипулатори на събития ни очакват проблеми със загуба на контекст. Нека разгледаме пример.

Да предположим, че имаме input поле:

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

Да предположим, че при клик върху това input поле се изпълнява анонимна функция и вътре в тази функция се стартира таймер, който всяка секунда извежда нещо в конзолата:

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

elem.addEventListener('click', function() {
  setInterval(function() {
    console.log('!!!'); // извеждаме нещо в конзолата
  }, 1000);
});

Дотук всичко работи правилно. Но сега да предположим, че искаме да извеждаме в конзолата value на нашия input - ни очаква изненада: в конзолата ще се извежда undefined:

javascriptelem.addEventListener('click', function() {
  setInterval(function() {
    console.log(this.value); // ще се извежда undefined
  }, 1000);
});

Цялата работа е в това, че се получава функция във функция: има външна анонимна функция, която се извиква при клик и вътрешна анонимна функция, която се стартира от таймера. Във външната функция this сочи към input полето, но във вътрешната - не. Имаме загуба на контекст.

Защо се извежда undefined, а не се появява грешка в конзолата, както беше в предишните уроци? Защото this във функцията, извикана чрез setInterval, сочи към window.

Това означава, че се опитваме да прочетем свойството value на обекта window, ето така: window.value, а такова свойство в него няма, и получаваме undefined (не грешка).

Нека поправим проблема чрез въвеждане на self:

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

Даден е следният код:

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

Авторът на кода е искал при натискане на бутона, стойността на този бутон да се увеличава всяка секунда с 1. Обаче, при натискане на бутона изобщо нищо не се случва. Поправете грешката в кода на автора. Напишете текст, в който дадете обяснение на автора на кода, защо е възникнала неговата грешка.