JavaScript-те таймерлер және контекстің жоғалуы
Оқиғаларды өңдеушілерде таймерлерді қолданған кезде бізді контекстің жоғалуы мәселесі күтіп тұрады. Мысал арқылы қарастырайық.
Бізде енгізу өрісі болсын:
<input id="elem" value="text">
Бұл енгізу өрісін басқанда анонимді функция орындалып, сол функция ішінде таймер іске қосылып, әр секунд сайын бірнәрсені консольге шығарады делік:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // бірнәрсені консольге шығарамыз
}, 1000);
});
Әзірше бәрі дұрыс жұмыс істейді. Бірақ енді
біз консольге өзіміздің енгізу өрісінің value
мәнін шығарғымыз келеді - бізді таңғалдыратын нәрсе күтіп тұр: консольде
undefined шығады:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // undefined шығады
}, 1000);
});
Мәселе мында, бізде функция функцияның ішінде пайда болады:
сыртқы анонимді функция бар (ол түймені басқанда шақырылады)
және ішкі анонимді функция бар (оны таймер іске қосады).
Сыртқы функцияда this енгізу өрісін көрсетеді,
бірақ ішкі функцияда - көрсетпейді. Контекст жоғалады.
Неге undefined шығады, ал консольде қате пайда болмайды,
яғни алдыңғы сабақтарда болғандай? Себебі setInterval
арқылы шақырылатын функция ішіндегі this
window объектісін көрсетеді.
Бұл біз window объектісінен value сипатын оқып әрекет жасаймыз дегенді білдіреді, мынаны: window.value,
ал ондай сипат жоқ, сондықтан біз
undefined аламыз (қате емес).
Мәселені self енгізу арқылы түзейік:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Мына код берілсін:
<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);
});
Кодтың авторы түймені басқан кезде,
сол түйменің мәні әр секунд сайын 1-ге өссе деп қалаған.
Алайда, түймені басқанда
ешнәрсе болмайды. Автордың қатесін түзеңіз.
Код авторына оның қатесінің неге пайда болғанын
түсіндіретін мәтінді жаз.