在偵測到事件監聽器時

傑夫波斯尼克
Jeff Posnick

彈出式測驗:傳遞至 addEventListener() 的第三個參數的用途為何?

如果您只認為 addEventListener() 只使用兩個參數,或是單純只對 false 的值進行硬式編碼,又會不太瞭解這個效果與泡泡有什麼關聯,請不用說吧?

更可設定的 addEventListener()

自網站問世以來,addEventListener() 方法已歷經得起時間考驗,而且新功能是透過第三個參數的進階版本設定。近期對方法定義所做的變更可讓開發人員透過設定物件提供其他選項,同時在有布林值參數或未指定選項時保持回溯相容性。

很高興在此宣布,Chrome 55 開始支援該設定物件中的 once 選項,以及 passive (在 Chrome 51 中實作) 和 capture 選項 (已在 Chrome 49 中實作)。例如:

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

您可以視需求混合搭配這些選項。

手動清理的好處

以上就是使用新 once 選項的語法,但這能帶來什麼好處呢?簡而言之,這樣您會提供專門為「一次完成」用途的事件監聽器。

根據預設,事件監聽器會在第一次呼叫後持續保留。對於某些類型的事件 (例如可多次點選的按鈕),事件監聽器就會持續保留下來。但在其他用途中,事件監聽器不需要使用事件監聽器,如果您的回呼只能執行一次,可能會導致不想要的行為。衛生開發人員一直選擇使用 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 事件監聽器回呼也不再使用,當此回呼結束後,回呼仍會位於該回呼範圍內。由於 data 變數是用於回呼內,因此也會存在於範圍內,而且絕不會收集垃圾。但如果透過 once 參數移除回呼,則函式本身和透過其範圍保留的任何項目都可能適合進行垃圾收集。

瀏覽器支援

Chrome 55 以上版本、Firefox 50 以上版本和 Safari 的 技術預覽 7 以上版本提供原生支援 once 選項。

許多 JavaScript UI 程式庫都提供建立事件監聽器的便利方法,有些則提供定義一次性事件的捷徑,其中最值得注意的是 jQuery 的 one() 方法。您還可以在 Andrea Giammarchidom4 程式庫中使用 polyfill。

感謝

感謝 Ingvar Stepanyan 對本文程式碼範例的意見回饋