Timers e perda de contexto em JavaScript
Ao usar timers em manipuladores de eventos, nos deparamos com problemas de perda de contexto. Vamos ver um exemplo.
Suponha que temos um input:
<input id="elem" value="text">
Suponha que ao clicar neste input, uma função anônima seja executada e dentro desta função um timer seja iniciado, imprimindo algo no console a cada segundo:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // imprimimos algo no console
}, 1000);
});
Até agora tudo funciona corretamente. Mas agora suponha
que queremos imprimir o value
do nosso input no console - nos aguarda uma surpresa: no console
será impresso undefined:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // irá imprimir undefined
}, 1000);
});
Tudo se deve ao fato de que temos uma função
dentro de uma função: existe a função anônima
externa, que é chamada no clique, e a função anônima
interna, que é iniciada pelo timer.
Na função externa, o this aponta
para o input, mas na interna - não. Ocorre uma
perda de contexto.
Por que é impresso undefined, e não surge
um erro no console, como foi em lições
anteriores? Porque o this dentro da função
chamada via setInterval, aponta
para o window.
Isso significa que estamos tentando ler a propriedade
value do objeto window, assim: window.value,
e tal propriedade não existe nele, e obtemos
undefined (não um erro).
Vamos corrigir o problema introduzindo self:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Suponha o seguinte código:
<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);
});
O autor do código queria que, ao clicar no botão,
o valor desse botão aumentasse em 1 a cada
segundo. No entanto, ao clicar no botão,
nada acontece. Corrija o erro
do autor do código. Escreva um texto no qual você
explica ao autor do código por que o erro
ocorreu.