Timere og tap av kontekst i JavaScript
Ved bruk av timere i hendelseshåndterere venter det problemer med tap av kontekst. La oss se på et eksempel.
La oss si at vi har et input-felt:
<input id="elem" value="text">
La oss si at ved klikk på dette input-feltet utløses en anonym funksjon, og inne i denne funksjonen starter en timer som hvert sekund skriver ut noe i konsollen:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // skriver ut noe i konsollen
}, 1000);
});
Så langt fungerer alt korrekt. Men la oss nå si at
vi ønsker å skrive ut value
fra vårt input-felt til konsollen - da venter det en overraskelse: i konsollen
vil det stå undefined:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // vil skrive ut undefined
}, 1000);
});
Hele poenget er at vi ender opp med en funksjon
innenfor en funksjon: det er en ytre anonym funksjon,
som kalles ved klikk, og en indre
anonym funksjon, som timeren starter.
I den ytre funksjonen peker this
på input-feltet, men i den indre - ikke. Det forekommer
et tap av kontekst.
Hvorfor skrives det ut undefined, og ikke kommer det
en feilmelding i konsollen,
som det gjorde i forrige
leksjoner? Fordi this inni funksjonen
som kalles via setInterval, peker
på window.
Det betyr at vi prøver å lese egenskapen
value fra objektet window, slik: window.value,
og en slik egenskap finnes ikke i den, og vi får
undefined (ikke en feil).
La oss rette problemet ved å innføre self:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
La oss si at vi har denne koden:
<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);
});
Kodeforfatteren ønsket at ved trykk på knappen,
skal verdien på denne knappen økes med 1 hvert sekund.
Men ved trykk på knappen
skjer det ingenting. Rett opp feilen
i kodeforfatterens kode. Skriv en tekst der du
gir en forklaring til kodeforfatteren om hvorfor feilen
oppstod.