หนึ่งครั้งที่ Listener เหตุการณ์

แบบทดสอบสั้นๆ: พารามิเตอร์ที่ 3 ที่ส่งไปยัง addEventListener() มีไว้เพื่ออะไร

ไม่ต้องอายหากคิดว่า addEventListener() ใช้พารามิเตอร์ได้เพียง 2 รายการ หรืออาจกำหนดค่า false แบบฮาร์ดโค้ดเสมอ โดยเข้าใจอย่างคร่าวๆ ว่าเกี่ยวข้องกับ… ฟองสบู่

addEventListener() ที่กําหนดค่าได้มากขึ้น

เมธอด addEventListener() พัฒนามาอย่างยาวนานตั้งแต่ยุคแรกๆ ของเว็บ และฟังก์ชันการทำงานแบบใหม่ได้รับการกําหนดค่าผ่านพารามิเตอร์ที่ 3 เวอร์ชันที่มีประสิทธิภาพมากขึ้น การเปลี่ยนแปลงล่าสุดในคําจํากัดความของเมธอดช่วยให้นักพัฒนาแอประบุตัวเลือกเพิ่มเติมผ่านออบเจ็กต์การกําหนดค่าได้ ขณะเดียวกันก็ยังคงใช้งานร่วมกับเวอร์ชันเก่าได้เมื่อมีพารามิเตอร์บูลีนหรือไม่ได้ระบุตัวเลือก

เรายินดีที่จะแจ้งให้ทราบว่า Chrome 55 เพิ่มการรองรับตัวเลือก once ในออบเจ็กต์การกําหนดค่านั้น ควบคู่ไปกับตัวเลือก passive (ใช้งานใน Chrome 51) และ capture (ใช้งานใน Chrome 49) เช่น

element.addEventListener('click', myClickHandler, {
    once: true,
    passive: true,
    capture: true
});

คุณผสมผสานตัวเลือกเหล่านั้นได้ตามกรณีการใช้งานของคุณ

ประโยชน์ของการทำความสะอาดหลังตัวเอง

นี่เป็นไวยากรณ์สําหรับการใช้ตัวเลือก once ใหม่ แต่ตัวเลือกนี้ทําอะไรให้คุณได้บ้าง กล่าวโดยย่อคือ คุณจะได้รับการฟังเหตุการณ์ที่ปรับให้เหมาะกับกรณีการใช้งานแบบ "ทำครั้งเดียวจบ"

โดยค่าเริ่มต้น โปรแกรมรับฟังเหตุการณ์จะยังคงอยู่หลังจากเรียกใช้ครั้งแรก ซึ่งเป็นสิ่งที่คุณต้องการสำหรับเหตุการณ์บางประเภท เช่น ปุ่มที่คลิกได้หลายครั้ง แต่สำหรับการใช้งานอื่นๆ การมี Listener เหตุการณ์อยู่ตลอดนั้นไม่จำเป็นและอาจทําให้ระบบทํางานในลักษณะที่ไม่พึงประสงค์หากคุณมีคอลแบ็กที่ต้องเรียกใช้เพียงครั้งเดียว นักพัฒนาซอฟต์แวร์ที่มีระเบียบเรียบร้อยมีตัวเลือกในการใช้ removeEventListener() เสมอเพื่อล้างข้อมูลอย่างชัดแจ้งตามรูปแบบต่างๆ เช่น

element.addEventListener('click', function cb(event) {
    // ...one-time handling of the click event...
    event.currentTarget.removeEventListener(event.type, cb);
});

โค้ดที่เทียบเท่าซึ่งใช้ประโยชน์จากพารามิเตอร์ once ใหม่จะสะอาดกว่าและไม่บังคับให้คุณติดตามชื่อเหตุการณ์ (event.type ในตัวอย่างก่อนหน้า) หรือการอ้างอิงฟังก์ชันการเรียกกลับ (cb)

element.addEventListener('click', function(event) {
    // ...one-time handling of the click event...
}, {once: true});

การล้างข้อมูลตัวแฮนเดิลเหตุการณ์ยังช่วยประหยัดหน่วยความจำได้ด้วย โดยระบบจะทำลายขอบเขตที่เชื่อมโยงกับฟังก์ชันการเรียกกลับ ซึ่งช่วยให้ระบบรวบรวมขยะตัวแปรที่บันทึกไว้ในขอบเขตนั้นได้ ต่อไปนี้เป็นตัวอย่างหนึ่งที่การระบุแหล่งที่มาจะมีประโยชน์

function setUpListeners() {
    var data = ['one', 'two', '...etc.'];

    window.addEventListener('load', function() {
    doSomethingWithSomeData(data);
    // data is now part of the callback's scope.
    });
}

โดยค่าเริ่มต้น ฟังก์ชันการเรียกกลับของ load event listener จะยังคงอยู่ในขอบเขตเมื่อเรียกใช้เสร็จแล้ว แม้ว่าจะไม่มีการใช้อีกเลยก็ตาม เนื่องจากมีการใช้ตัวแปร data ภายในการเรียกกลับ ตัวแปรดังกล่าวจะยังคงอยู่ในขอบเขตและไม่มีการรวบรวมขยะ อย่างไรก็ตาม หากนำการเรียกกลับออกผ่านพารามิเตอร์ once ทั้งฟังก์ชันเองและทุกอย่างที่ยังคงทำงานอยู่ผ่านขอบเขตของฟังก์ชันนั้นอาจมีสิทธิ์ได้รับการรวบรวมขยะ

การสนับสนุนเบราว์เซอร์

Chrome 55 ขึ้นไป, Firefox 50 ขึ้นไป และ ตัวอย่างเทคโนโลยี 7 ขึ้นไปของ Safari มีการรองรับตัวเลือก once ในตัว

ไลบรารี UI ของ JavaScript จํานวนมากมีเมธอดที่สะดวกสําหรับการสร้าง EventListener และบางรายการมีทางลัดสําหรับการกําหนดเหตุการณ์แบบครั้งเดียว ซึ่งที่น่าสังเกตที่สุดคือเมธอด one() ของ jQuery นอกจากนี้ยังมี polyfill เป็นส่วนหนึ่งของdom4 library ของ Andrea Giammarchi

ขอขอบคุณ

ขอขอบคุณ Ingvar Stepanyan ที่ให้ความคิดเห็นเกี่ยวกับโค้ดตัวอย่างในโพสต์นี้