JavaScript 中匿名函数的 removeEventListener

IT技术 javascript safari dom-events anonymous-function
2021-02-06 14:34:15

我有一个包含方法的对象。这些方法被放入匿名函数内的对象中。它看起来像这样:

var t = {};
window.document.addEventListener("keydown", function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
});  

(还有很多代码,但这足以说明问题)

现在我想在某些情况下停止事件侦听器。因此,我正在尝试执行 removeEventListener,但我不知道如何执行此操作。我在其他问题中读到,不可能在匿名函数上调用 removeEventListener ,但在这种情况下也是如此吗?

我在匿名函数中创建了一个方法,因此我认为这是可能的。看起来像这样:

t.disable = function() {
    window.document.removeEventListener("keydown", this, false);
}

为什么我不能这样做?

有没有其他(好的)方法可以做到这一点?

奖金信息;这只能在 Safari 中工作,因此缺少 IE 支持。

6个回答

如果您在实际函数中,则可以使用arguments.callee 作为对该函数的引用。如:

button.addEventListener('click', function() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', arguments.callee);
});

编辑: 如果您在严格模式 ( "use strict";)下工作,这将不起作用

正如 Mozilla 中所述:“警告:ECMAScript (ES5) 的第 5 版禁止在严格模式下使用 arguments.callee()。通过给函数表达式一个名称或使用函数声明来避免使用 arguments.callee()必须自称。”
2021-03-18 14:34:15
这很好,因为它保留了匿名函数的优点(不污染命名空间等)。
2021-03-22 14:34:15
在 WinJS 应用程序中试过这个,得到下一个错误:“在严格模式下不允许访问参数对象的‘被调用者’属性”
2021-03-30 14:34:15
给内联函数一个名字,你就可以引用它而无需求助于arguments.callee: button.addEventListener('click', function handler() { this.removeEventListener('click', handler); });
2021-04-09 14:34:15
@ValentinKantor:那是因为代码中有“严格使用”;语句,并且您不能在严格模式下使用 callee。
2021-04-10 14:34:15

我相信这是匿名函数的重点,它缺少名称或引用它的方法。

如果我是你,我会创建一个命名函数,或者把它放在一个变量中,这样你就可以引用它。

var t = {};
var handler = function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
};
window.document.addEventListener("keydown", handler);

然后您可以通过以下方式将其删除

window.document.removeEventListener("keydown", handler);   
感谢你的回复。我去了: var 处理程序;window.document.addEventListener("keydown", handler = function(e) { 但我不明白为什么“this”不引用事件侦听器。事件侦听器不应该是一个对象吗?
2021-03-24 14:34:15
@bitkid:在处理函数内部(假设它不是箭头函数), thethis指的是添加到侦听器的元素,而不是事件本身(即参数e)。因此this === e.currentTarget阅读developer.mozilla.org/en-US/docs/Web/API/EventTarget/...
2021-04-02 14:34:15
非常感谢你。这是最有帮助的。
2021-04-06 14:34:15
我试图这样做是为了阻止网站上真正持久的广告。我知道这是匿名函数的重点,但这并不意味着我不想知道如何去做。
2021-04-07 14:34:15
this关键字可能会造成混淆。阅读它的好地方是quirksmode.org/js/this.html
2021-04-11 14:34:15

在严格模式下工作Otto Nascarella解决方案的一个版本是:

button.addEventListener('click', function handler() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', handler);
});
这可能不是正确的方法,但这是最简单的方法。
2021-03-28 14:34:15
我很好奇为什么这可能不是正确的方法
2021-04-01 14:34:15
这在 VueJS 指令的上下文中起作用。我创建了一个方法,我只希望它运行一次。
2021-04-10 14:34:15
美丽的解决方案!
2021-04-12 14:34:15

在现代浏览器中,您可以执行以下操作...

button.addEventListener( 'click', () => {
    alert( 'only once!' );
}, { once: true } );

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters

很酷,直到您发现没有任何版本的 IE 或 edge < 16 实际上支持此功能。至少在 5 年内我们可以使用它,因为那时 IE 将(阅读:应该)被弃用,Edge 将取而代之,它将使用 webkit 引擎而不是他们自己的“EdgeHTML”东西。
2021-04-06 14:34:15
使用这个用于 DOM Level 4 条目的polyfill,你应该没问题 npmjs.com/package/dom4
2021-04-08 14:34:15
window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));  

可能是几个匿名函数,keydown 1

警告:仅适用于Chrome Dev Tools& 不能在代码中使用链接

谢谢,你解决了一个谜语,至少在 Chrome 中,因为许多笑话说不可能。伙计,你就像……蝙蝠侠!
2021-03-19 14:34:15
getEventListeners 似乎是 Chrome Dev-tools 的一部分,所以除了调试之外没有其他用途。
2021-03-24 14:34:15
刚刚尝试过,确认它仅在 Devtools 中可用,而在包含在页面内的脚本中时不可用。
2021-03-26 14:34:15