Timers en konteksverlies in JavaScript
By die gebruik van timers in gebeurtenishanteerders loop ons teen probleme met konteksverlies. Kom ons kyk na 'n voorbeeld.
Gestel ons het 'n invoerveld:
<input id="elem" value="text">
Gestel by 'n klik op hierdie invoerveld word 'n anonieme funksie geaktiveer en binne hierdie funksie word 'n timer begin wat elke sekonde iets in die konsole uitvoer:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // voer iets in die konsole uit
}, 1000);
});
Tot dusver werk alles reg. Maar gestel nou
ons wil die invoerveld se value
in die konsole uitvoer - ons wag 'n verrassing: in die konsole
sal undefined uitgevoer word:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // sal undefined uitvoer
}, 1000);
});
Die hele saak is dat ons 'n funksie
in 'n funksie het: daar is 'n buitenste anonieme funksie,
wat by 'n klik geaktiveer word, en 'n innerlike
anonieme funksie wat deur die timer begin word.
In die buitenste funksie verwys this
na die invoerveld, maar in die innerlike een - nie. Daar is
konteksverlies.
Hoekom word undefined uitgevoer, en nie 'n
fout in die konsole gegooi nie, soos in vorige
lesse? Omdat this binne die funksie
wat deur setInterval geroep word, na
window verwys.
Dit beteken dat ons probeer om die eienskap
value van die objek window te lees, soos volg: window.value,
maar so 'n eienskap bestaan nie daarin nie, en ons kry
undefined (nie 'n fout nie).
Kom ons los die probleem op deur self in te voer:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Gestel die volgende kode word gegee:
<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);
});
Die outeur van die kode wou hê dat met die druk van die knoppie,
die waarde van hierdie knoppie elke sekonde met 1 vermeerder.
Met die druk op die knoppie gebeur egter
niks nie. Korrigeer die outeur se fout.
Skryf 'n teks waarin jy
'n verduideliking aan die outeur van die kode gee oor hoekom sy
fout ontstaan het.