หนึ่งครั้งที่ 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 เหตุการณ์ที่ปรับให้เหมาะกับกรณีการใช้งานแบบ "ครั้งเดียวและเสร็จสิ้น"

โดยค่าเริ่มต้น Listener เหตุการณ์จะยังคงอยู่หลังจากเรียกครั้งแรกเป็นครั้งแรก ซึ่งเป็นสิ่งที่คุณต้องการสำหรับเหตุการณ์บางประเภท เช่น ปุ่มที่คลิกได้หลายครั้ง อย่างไรก็ตาม สำหรับการใช้งานอื่นๆ คุณไม่จำเป็นต้องมี 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.
    });
}

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

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

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

ไลบรารี UI ของ JavaScript จำนวนมากมีวิธีอำนวยความสะดวกในการสร้าง Listener เหตุการณ์ และบางรายการก็มีทางลัดในการกำหนดเหตุการณ์ที่เกิดขึ้นครั้งเดียว สิ่งที่โดดเด่นที่สุดคือ เมธอด one() ของ jQuery นอกจากนี้ ยังมีโพลีฟิลให้บริการด้วย โดยเป็นส่วนหนึ่งของคลัง dom4 ของ Andrea Giammarchi

ขอขอบคุณ

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