Temporizadores y pérdida de contexto en JavaScript
Al usar temporizadores en manejadores de eventos, nos enfrentamos a problemas de pérdida de contexto. Veamos un ejemplo.
Supongamos que tenemos un input:
<input id="elem" value="text">
Supongamos que al hacer clic en este input se ejecute una función anónima y dentro de esta función se inicie un temporizador que muestre algo en la consola cada segundo:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // mostramos algo en la consola
}, 1000);
});
Hasta ahora todo funciona correctamente. Pero ahora supongamos que
queremos mostrar en la consola el value
de nuestro input - nos espera una sorpresa: en la consola
se mostrará undefined:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // se mostrará undefined
}, 1000);
});
El problema es que tenemos una función
dentro de otra función: está la función anónima externa,
que se llama al hacer clic, y la función anónima interna,
que inicia el temporizador.
En la función externa, this apunta
al input, pero en la interna, no. Tiene lugar
una pérdida de contexto.
¿Por qué se muestra undefined y no se produce
un error en la consola, como en lecciones anteriores?
Porque this dentro de la función
invocada a través de setInterval, apunta
a window.
Esto significa que estamos intentando leer la propiedad
value del objeto window, así: window.value,
y como no existe tal propiedad en él, obtenemos
undefined (no un error).
Solucionemos el problema introduciendo self:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Supongamos que tenemos este 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);
});
El autor del código quería que, al pulsar el botón,
el valor de este botón aumentara en 1 cada segundo.
Sin embargo, al pulsar el botón no sucede
nada en absoluto. Corrige el error del autor del código.
Escribe un texto en el que des una explicación al autor del código sobre por qué se produjo su error.