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 көбөйүүсүн каалаган. Бирок,
баскычты басканда эч нерсе болбойт. Коддун авторунун
катасын оңдонгула. Текст жазып, коддун авторуна анын
катасынын себебин түшүндүрүп бергиле.