ไทเมอร์และการสูญเสียคอนเท็กซ์ใน JavaScript

เมื่อใช้ไทเมอร์ในอีเวนต์แฮนด์เลอร์ เรามักจะพบปัญหาการสูญเสียคอนเท็กซ์ ลองดูตัวอย่างกัน

สมมติว่าเรามีอินพุต:

html<input id="elem" value="text">

สมมติว่าเมื่อคลิกที่อินพุตนี้ ฟังก์ชันนิรนาม จะทำงาน และภายในฟังก์ชันนั้นจะมีไทเมอร์ ที่ทำงานทุกวินาทีเพื่อแสดงผลบางอย่าง ในคอนโซล:

javascriptlet elem = document.querySelector('#elem');

elem.addEventListener('click', function() {
  setInterval(function() {
    console.log('!!!'); // แสดงผลบางอย่างในคอนโซล
  }, 1000);
});

ทุกอย่างทำงานได้ถูกต้อง แต่ตอนนี้สมมติว่า เราต้องการแสดงผลค่า value ของอินพุตของเราในคอนโซล - เราจะต้องประหลาดใจ: ในคอนโซล จะแสดงผลเป็น undefined:

javascriptelem.addEventListener('click', function() {
  setInterval(function() {
    console.log(this.value); // จะแสดงผลเป็น undefined
  }, 1000);
});

ทั้งหมดนี้เป็นเพราะเรามีฟังก์ชัน ภายในฟังก์ชัน: มีฟังก์ชันนิรนามภายนอก ที่ถูกเรียกเมื่อคลิก และฟังก์ชันนิรนามภายใน ที่ถูกเรียกโดยไทเมอร์ ในฟังก์ชันภายนอก this ชี้ไปที่ อินพุต แต่ในฟังก์ชันภายใน - ไม่ นี่คือกรณีของ การสูญเสียคอนเท็กซ์

ทำไมจึงแสดงผล undefined และไม่เกิด ข้อผิดพลาดในคอนโซล อย่างที่เคยเป็นในบทเรียนก่อนๆ? เพราะว่า this ภายในฟังก์ชัน ที่ถูกเรียกผ่าน setInterval ชี้ไปที่ window

นี่หมายความว่าเราพยายามอ่านคุณสมบัติ value จากออบเจ็กต์ window แบบนี้: window.value แต่คุณสมบัตินั้นไม่มีอยู่ในนั้น และเราได้ undefined (ไม่ใช่ข้อผิดพลาด)

มาแก้ไขปัญหาด้วยการนำเข้า self:

javascriptelem.addEventListener('click', function() {
  let self = this;
  
  setInterval(function() {
    console.log(self.value);
  }, 1000);
});
Задание 1

สมมติว่าโค้ดนี้ถูกกำหนด:

html<input type="button" id="elem" value="1">
javascriptlet elem = document.querySelector('#elem');

elem.addEventListener('click', function() {
  setInterval(function() {
    this.value = Number(elem.value) + 1;
  }, 1000);
});

ผู้เขียนโค้ดต้องการให้เมื่อกดปุ่ม ค่าของปุ่มนี้จะเพิ่มขึ้นทุกวินาที ทีละ 1 อย่างไรก็ตาม เมื่อกดปุ่ม แล้วไม่มีอะไรเกิดขึ้นเลย แก้ไขข้อผิดพลาด ของผู้เขียนโค้ด เขียนข้อความที่คุณ จะให้คำอธิบายแก่ผู้เขียนโค้ดว่าทำไมจึงเกิด ข้อผิดพลาดของเขาขึ้น