Timer e perdita del contesto in JavaScript
Quando si utilizzano i timer nei gestori di eventi, ci si imbatte in problemi di perdita del contesto. Diamo un'occhiata a un esempio.
Supponiamo di avere un input:
<input id="elem" value="text">
Supponiamo che al click su questo input venga eseguita una funzione anonima e all'interno di questa funzione venga avviato un timer, che ogni secondo stampa qualcosa nella console:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // stampiamo qualcosa nella console
}, 1000);
});
Finora tutto funziona correttamente. Ma ora supponiamo
di voler stampare nella console il value
del nostro input - ci aspetta una sorpresa: nella console
verrà stampato undefined:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // stamperà undefined
}, 1000);
});
Il punto è che abbiamo una funzione all'interno di una funzione:
c'è una funzione anonima esterna, che viene chiamata al click, e una funzione
anonima interna, che viene avviata dal timer.
Nella funzione esterna this si riferisce
all'input, ma in quella interna - no. Si verifica una
perdita del contesto.
Perché viene stampato undefined, e non viene generato
un errore nella console, come è accaduto nelle lezioni
precedenti? Perché this all'interno della funzione
chiamata tramite setInterval, si riferisce
a window.
Ciò significa che stiamo tentando di leggere la proprietà
value dall'oggetto window, in questo modo: window.value,
ma tale proprietà non esiste in esso, e quindi otteniamo
undefined (non un errore).
Risolviamo il problema introducendo self:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Supponiamo di avere questo codice:
<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);
});
L'autore del codice voleva che, alla pressione del pulsante,
il valore di questo pulsante aumentasse di 1 ogni secondo.
Tuttavia, alla pressione del pulsante non succede assolutamente
niente. Correggi l'errore dell'autore del codice. Scrivi un testo in cui
spieghi all'autore del codice perché si è verificato il suo errore.