Timere og tab af kontekst i JavaScript
Ved brug af timere i event handlers venter der os problemer med tab af kontekst. Lad os se på et eksempel.
Lad os sige, at vi har et input felt:
<input id="elem" value="text">
Lad ved klik på dette input felt en anonym funktion blive udført, og inde i denne funktion startes en timer, som hvert sekund udskriver noget i konsollen:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // udskriver noget i konsollen
}, 1000);
});
Indtil nu virker alt korrekt. Men lad os nu sige,
at vi ønsker at udskrive input feltets value
i konsollen - her venter der os en overraskelse: i konsollen
vil der blive udskrevet undefined:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // vil udskrive undefined
}, 1000);
});
Hele pointen er, at vi ender med en funktion
inde i en funktion: der er en ydre anonym funktion,
som kaldes ved klik, og en indre
anonym funktion, som timeren starter.
I den ydre funktion peger this
på input feltet, men i den indre - gør den ikke. Der forekommer
et tab af kontekst.
Hvorfor bliver der udskrevet undefined, og ikke kastet
en fejl i konsollen, som det var i de foregående
lektioner? Fordi this inde i funktionen,
som kaldes via setInterval, peger
på window.
Det betyder, at vi forsøger at læse egenskaben
value fra objektet window, sådan her: window.value,
og en sådan egenskab findes ikke i det, og vi får
undefined (ikke en fejl).
Lad os rette problemet ved at indføre self:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Lad os sige, at der er givet sådan en kode:
<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);
});
Kodens forfatter ønskede, at ved tryk på knappen,
ville værdien af denne knap hvert sekund stige
med 1. Men ved tryk på knappen
sker der overhovedet intet. Ret forfatterens fejl.
Skriv en tekst, hvor du
giver en forklaring til forfatteren af koden, hvorfor hans fejl
opstod.