JavaScript 中匿名函数的 removeEventListener

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4950115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:55:17  来源:igfitidea点击:

removeEventListener on anonymous functions in JavaScript

javascriptsafaridom-eventsanonymous-function

提问by bitkid

I have an object that has methods in it. These methods are put into the object inside an anonymous function. It looks like this:

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

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);
    };
});  

(there is a lot more code, but this is enough to show the problem)

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

Now I want to stop the event listener in some cases. Therefore I am trying to do a removeEventListener but I can't figure out how to do this. I have read in other questions that it is not possible to call removeEventListener on anonymous functions, but is this also the case in this situation?

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

I have a method in t created inside the anonymous function and therefore I thought it was possible. Looks like this:

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

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

Why can't I do this?

为什么我不能这样做?

Is there any other (good) way to do this?

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

Bonus info; this only has to work in Safari, hence the missing IE support.

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

采纳答案by Adam Heath

I believe that is the point of an anonymous function, it lacks a name or a way to reference it.

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

If I were you I would just create a named function, or put it in a variable so you have a reference to it.

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

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);

You can then remove it by

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

window.document.removeEventListener("keydown", handler);   

回答by Otto Nascarella

if you are inside the actual function, you can use arguments.callee as a reference to the function. as in:

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

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

EDIT:This will not work if you are working in strict mode ("use strict";)

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

回答by Melle

A version of Otto Nascarella's solution that works in strict mode is:

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

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

回答by Isayevskiy_Sergey

window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));  

May be several anonymous functions, keydown1

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

Warning: only works in Chrome Dev Tools& cannot be used in code: link

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

回答by shunryu111

in modern browsers you can do the following...

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

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

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

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

回答by shunryu111

This is not ideal as it removes all, but might work for your needs:

这并不理想,因为它会删除所有内容,但可能会满足您的需求:

z = document.querySelector('video');
z.parentNode.replaceChild(z.cloneNode(1), z);

Cloning a node copies all of its attributes and their values, including intrinsic (in–line) listeners. It does not copy event listeners added using addEventListener()

克隆节点会复制其所有属性及其值,包括内在(内联)侦听器。它不会复制使用 addEventListener() 添加的事件侦听器

Node.cloneNode()

Node.cloneNode()

回答by Fred Gandt

A not so anonymous option

一个不太匿名的选择

element.funky = function() {
    console.log("Click!");
};
element.funky.type = "click";
element.funky.capt = false;
element.addEventListener(element.funky.type, element.funky, element.funky.capt);
// blah blah blah
element.removeEventListener(element.funky.type, element.funky, element.funky.capt);

Since receiving feedbackfrom Andy (quite right, but as with many examples, I wished to show a contextual expansion of the idea), here's a less complicatedexposition:

自从收到安迪的反馈非常正确,但与许多示例一样,我希望展示这个想法的上下文扩展),这里有一个不太复杂的说明

<script id="konami" type="text/javascript" async>
    var konami = {
        ptrn: "38,38,40,40,37,39,37,39,66,65",
        kl: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    };
    document.body.addEventListener( "keyup", function knm ( evt ) {
        konami.kl = konami.kl.slice( -9 );
        konami.kl.push( evt.keyCode );
        if ( konami.ptrn === konami.kl.join() ) {
            evt.target.removeEventListener( "keyup", knm, false );

            /* Although at this point we wish to remove a listener
               we could easily have had multiple "keyup" listeners
               each triggering different functions, so we MUST
               say which function we no longer wish to trigger
               rather than which listener we wish to remove.

               Normal scoping will apply to where we can mention this function
               and thus, where we can remove the listener set to trigger it. */

            document.body.classList.add( "konami" );
        }
    }, false );
    document.body.removeChild( document.getElementById( "konami" ) );
</script>

This allows an effectively anonymous function structure, avoids the use of the practically deprecated callee, and allows easy removal.

这允许有效的匿名函数结构,避免使用实际上已弃用的callee,并允许轻松删除。

Incidentally: The removal of the script element immediately after setting the listener is a cute trick for hiding code one would prefer wasn't starkly obvious to prying eyes (would spoil the surprise;-)

顺便说一句:在设置监听后立即去除脚本元素是隐藏代码人们会喜欢可爱的诀窍是不是赤裸裸地明显窥探(就没有惊喜了;-)

So the method (more simply) is:

所以方法(更简单)是:

element.addEventListener( action, function name () {
    doSomething();
    element.removeEventListener( action, name, capture );
}, capture );

回答by Yash

JavaScript: addEventListenermethod registers the specified listener on the EventTarget(Element|document|Window) it's called on.

JavaScript: addEventListener方法在它被调用的 EventTarget(Element|document|Window) 上注册指定的侦听器。

EventTarget.addEventListener(event_type, handler_function, Bubbling|Capturing);

事件目标。addEventListener( event_type, handler_function, Bubbling|Capturing);

Mouse, Keyboard eventsExample test in WebConsole:

鼠标、键盘事件WebConsole 中的示例测试:

var keyboard = function(e) {
    console.log('Key_Down Code : ' + e.keyCode);
};
var mouseSimple = function(e) {
    var element = e.srcElement || e.target;
    var tagName = element.tagName || element.relatedTarget;
    console.log('Mouse Over TagName : ' + tagName);    
};
var  mouseComplex = function(e) {
    console.log('Mouse Click Code : ' + e.button);
} 

window.document.addEventListener('keydown',   keyboard,      false);
window.document.addEventListener('mouseover', mouseSimple,   false);
window.document.addEventListener('click',     mouseComplex,  false);

removeEventListenermethod removes the event listener previously registered with EventTarget.addEventListener().

removeEventListener方法移除先前使用 EventTarget.addEventListener() 注册的事件侦听

window.document.removeEventListener('keydown',   keyboard,     false);
window.document.removeEventListener('mouseover', mouseSimple,  false);
window.document.removeEventListener('click',     mouseComplex, false);

caniuse

我可以用吗

回答by Jonatas Walker

To give a more up-to-date approach to this:

对此,要提供更新的方法:

//one-time fire
element.addEventListener('mousedown', {
  handleEvent: function (evt) {
    element.removeEventListener(evt.type, this, false);
  }
}, false);

回答by Gark Garcia

I have stumbled across the same problem and this was the best solution I could get:

我偶然发现了同样的问题,这是我能得到的最佳解决方案:

/*Adding the event listener (the 'mousemove' event, in this specific case)*/
element.onmousemove = function(event) {
    /*do your stuff*/
};
/*Removing the event listener*/
element.onmousemove = null;

Please keep in mind I have only tested this for the windowelement and for the 'mousemove'event, so there could be some problems with this approach.

请记住,我只针对window元素和'mousemove'事件对此进行了测试,因此这种方法可能存在一些问题。