Timers en contextverlies in JavaScript
Bij het gebruik van timers in gebeurtenisafhandelaars worden we geconfronteerd met problemen van contextverlies. Laten we een voorbeeld bekijken.
Stel we hebben een invoerveld:
<input id="elem" value="text">
Stel dat bij een klik op dit invoerveld een anonieme functie wordt uitgevoerd en binnen deze functie een timer start, die elke seconde iets in de console uitvoert:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // voer iets uit in de console
}, 1000);
});
Tot nu toe werkt alles correct. Maar stel dat we nu
de value van ons invoerveld in de console willen uitvoeren
- dan wacht ons een verrassing: in de console
wordt undefined uitgevoerd:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // zal undefined uitvoeren
}, 1000);
});
Het punt is dat we te maken hebben met een functie
in een functie: er is een externe anonieme functie,
die wordt aangeroepen bij een klik en een interne
anonieme functie, die door de timer wordt gestart.
In de externe functie verwijst this
naar het invoerveld, maar in de interne - niet. Er
treedt contextverlies op.
Waarom wordt undefined uitgevoerd, en niet
een foutmelding in de console, zoals in eerdere
lessen? Omdat this binnen de functie,
die wordt aangeroepen via setInterval, verwijst
naar window.
Dit betekent dat we proberen de eigenschap
value te lezen van het object window, zo: window.value,
en zo'n eigenschap bestaat daar niet, en we krijgen
undefined (geen fout).
Laten we het probleem oplossen door self te introduceren:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Stel we hebben de volgende code:
<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);
});
De auteur van de code wilde dat bij het klikken op de knop,
de waarde van deze knop elke seconde met 1 zou toenemen.
Echter, bij het klikken op de knop
gebeurt er helemaal niets. Verbeter de fout
van de auteur van de code. Schrijf een tekst waarin je
een uitleg geeft aan de auteur van de code, waarom zijn fout
is ontstaan.