# Таймеры и потеря контекста в JavaScript

При использовании таймеров в обработчиках событий нас поджидают проблемы с потерей контекста. Давайте посмотрим на примере.

Пусть у нас есть инпут:

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

Пусть по клику на этот инпут сработает анонимная функция и внутри этой функции запустится таймер, каждую секунду выводящий что-нибудь в консоль:

`let elem = document.querySelector('#elem'); elem.addEventListener('click', function() { setInterval(function() { console.log('!!!'); // что-нибудь выводим в консоль }, 1000); });`

Пока все работает верно. Но пусть теперь мы хотим выводить в консоль `value` нашего инпута - нас ждет сюрприз: в консоль будет выводится `undefined`:

`elem.addEventListener('click', function() { setInterval(function() { console.log(this.value); // будет выводится undefined }, 1000); });`

Все дело в том, что у нас получается функция в функции: есть внешняя анонимная функция, которая вызывается по клику и внутренняя анонимная функция, которую запускает таймер. Во внешней функции `this` указывает на инпут, но во внутренней - нет. Имеет место потеря контекста.

Почему выводится `undefined`, а не вываливается ошибка в консоль, как это было в предыдущих уроках? Потому что `this` внутри функции, вызываемой через `setInterval`, указывает на `window`.

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

Поправим проблему введением `self`:

`elem.addEventListener('click', function() { let self = this; setInterval(function() { console.log(self.value); }, 1000); });`

Пусть дан такой код:

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

Автор кода хотел, чтобы по нажатию на кнопку, значение этой кнопки каждую секунду увеличивалось на `1`. Однако, по нажатию на кнопку вообще ничего не происходит. Исправьте ошибку автора кода. Напишите текст, в котором вы дадите объяснение автору кода, почему возникла его ошибка.

← →
↑
en ru