JavaScript中的匿名函数的removeEventListener

时间:2011-02-09 20:31:39

标签: javascript javascript-events anonymous-function

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

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中工作,因此缺少即支持。

14 个答案:

答案 0 :(得分:89)

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

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

修改 如果您在严格模式("use strict";

中工作,这将无效

答案 1 :(得分:60)

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

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

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

答案 2 :(得分:35)

Otto Nascarella在严格模式下运行的解决方案版本为:

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

答案 3 :(得分:9)

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

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

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

答案 4 :(得分:2)

一个不那么匿名的选项

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

自从Andy收到反馈非常正确,但与许多示例一样,我希望展示这个想法的上下文扩展),这里是更少复杂的阐述:

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

这允许有效的匿名函数结构,避免使用practically deprecated callee,并允许轻松删除。

顺便提一下:设置监听器后立即删除脚本元素是隐藏代码的一个可爱技巧,人们更喜欢窥探眼睛并不是很明显(会破坏意外< / em>; - )

所以方法(更简单)是:

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

答案 5 :(得分:2)

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

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

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

Node.cloneNode()

答案 6 :(得分:2)

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

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

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

答案 7 :(得分:1)

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

EventTarget。addEventListenerevent_type,handler_function,Bubbling|Capturing);

鼠标,键盘events 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);

<强> removeEventListener 方法删除先前使用EventTarget.addEventListener()注册的事件侦听器。

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

caniuse

答案 8 :(得分:1)

为此提供更新的方法:

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

答案 9 :(得分:0)

根据您的要求,可能不是最佳解决方案。我还没有确定一种有效的方法来删除与事件监听器调用内联声明的匿名函数。

我个人使用变量存储Inf并在事件侦听器调用之外声明函数,例如:

<target>

const target = document.querySelector('<identifier>');   function myFunc(event) { function code;

}

然后删除监听器:

target.addEventListener('click', myFunc);

不是您将收到的最高建议,但要删除匿名函数,我发现唯一有用的解决方案是删除然后替换HTML元素。我相信必须有一个更好的香草JS方法,但我还没有看到它。

答案 10 :(得分:0)

我偶然发现了相同的问题,这是我可以获得的最佳解决方案:

/*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;

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

答案 11 :(得分:0)

我知道这是一个比较老的话题,但我想我可能会为那些觉得有用的人投入两美分。

脚本(关于非创意方法名称的道歉):

window.Listener = {
    _Active: [],
    remove: function(attached, on, callback, capture){
        for(var i = 0; i < this._Active.length; i++){
            var current = this._Active[i];
            if(current[0] === attached && current[1] === on && current[2] === callback){
                attached.removeEventListener(on, callback, (capture || false));
                return this._Active.splice(i, 1);
            }
        }
    }, removeAtIndex(i){
        if(this._Active[i]){
            var remove = this._Active[i];
            var attached = remove[0], on = remove[1], callback = remove[2];
            attached.removeEventListener(on, callback, false);
            return this._Active.splice(i, 1);
        }
    }, purge: function(){
        for(var i = 0; i < this._Active.length; i++){
            var current = this._Active[i];
            current[0].removeEventListener(current[1], current[2]);
            this._Active.splice(i, 1);
        }
    }, declare: function(attached, on, callback, capture){
        attached.addEventListener(on, callback, (capture || false));
        if(this._Active.push([attached, on, callback])){
            return this._Active.length - 1;
        }
    }
};

您可以像这样使用它:

// declare a new onclick listener attached to the document
var clickListener = Listener.declare(document, "click" function(e){
    // on click, remove the listener and log the clicked element
    console.log(e.target);
    Listener.removeAtIndex(clickListener);
});

// completely remove all active listeners 
// (at least, ones declared via the Listener object)
Listener.purge();

// works exactly like removeEventListener
Listener.remove(element, on, callback);

答案 12 :(得分:-1)

我刚刚遇到了与复制保护wordpress插件类似的问题。代码是:

function disableSelection(target){
 if (typeof target.onselectstart!="undefined") //For IE 
  target.onselectstart=function(){return false}
 else if (typeof target.style.MozUserSelect!="undefined") //For Firefox
  target.style.MozUserSelect="none"
 else //All other route (For Opera)
  target.onmousedown=function(){return false}
target.style.cursor = "default"
}

然后通过松散放置将其启动

<script type="text/javascript">disableSelection(document.body)</script>.

我通过将其他匿名函数附加到该事件上来解决了这个问题:

document.body.onselectstart = function() { return true; };

答案 13 :(得分:-4)

window.document.onkeydown = function(){};