问题
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?
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.
回答1:
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);
回答2:
if you are inside the actual function, you can use arguments.callee as a reference to the function. as in:
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";
)
回答3:
A version of Otto Nascarella's solution that works in strict mode is:
button.addEventListener('click', function handler() {
///this will execute only once
alert('only once!');
this.removeEventListener('click', handler);
});
回答4:
window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));
May be several anonymous functions, keydown1
Warning: only works in Chrome Dev Tools
& cannot be used in code: link
回答5:
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 feedback from Andy (quite right, but as with many examples, I wished to show a contextual expansion of the idea), here's a less complicated exposition:
<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.
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 );
回答6:
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()
Node.cloneNode()
回答7:
in modern browsers you can to the following...
button.addEventListener( 'click', () => {
alert( 'only once!' );
}, { once: true } );
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters
回答8:
JavaScript: addEventListener method registers the specified listener on the EventTarget(Element|document|Window) it's called on.
EventTarget.addEventListener(event_type, handler_function, Bubbling|Capturing);
Mouse, Keyboard events Example test in 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 method removes the event listener previously registered with EventTarget.addEventListener().
window.document.removeEventListener('keydown', keyboard, false);
window.document.removeEventListener('mouseover', mouseSimple, false);
window.document.removeEventListener('click', mouseComplex, false);
caniuse
回答9:
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);
回答10:
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 window
element and for the 'mousemove'
event, so there could be some problems with this approach.
回答11:
Possibly not the best solution in terms of what you are asking. I have still not determined an efficient method for removing anonymous function declared inline with the event listener invocation.
I personally use a variable to store the <target>
and declare the function outside of the event listener invocation eg:
const target = document.querySelector('<identifier>');
function myFunc(event) {
function code;
}
target.addEventListener('click', myFunc);
Then to remove the listener:
target.removeEventListener('click', myFunc);
Not the top recommendation you will receive but to remove anonymous functions the only solution I have found useful is to remove then replace the HTML element. I am sure there must be a better vanilla JS method but I haven't seen it yet.
回答12:
I know this is a fairly old thread, but thought I might put in my two cents for those who find it useful.
The script (apologies about the uncreative method names):
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;
}
}
};
And you can use it like so:
// 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);
回答13:
window.document.onkeydown = function(){};
来源:https://stackoverflow.com/questions/4950115/removeeventlistener-on-anonymous-functions-in-javascript