事件监听器

杰夫·波斯尼克
Jeff Posnick

小测验:传递给 addEventListener() 的第三个参数有什么用途?

如果您以为 addEventListener() 只接受两个参数,或者只是总是对 false 的值进行硬编码,而模棱两可地理解它与气泡有关,请不要感到尴尬。

可配置的 addEventListener() 更多

自 Web 问世以来,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 界面库都提供了创建事件监听器的便捷方法,有些库具有用于定义一次性事件的快捷方式,其中最值得注意的是 jQuery 的 one() 方法Andrea Giammarchidom4中还提供了 polyfill。

此致

感谢 Ingvar Stepanyan 对本博文中的示例代码提供了反馈