safari - ta bortEventListener på anonyma funktioner i JavaScript
Jag har ett objekt som har metoder i sig. Dessa metoder läggs in i objektet inuti en anonym funktion. Det ser ut så här:
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);
};
});
(det finns mycket mer kod, men detta är tillräckligt för att visa problemet)
Nu vill jag stoppa händelselyssnaren i vissa fall. Därför försöker jag göra en removeEventListener men jag kan inte lista ut hur man gör detta. Jag har läst i andra frågor att det inte är möjligt att kalla removeEventListener på anonyma funktioner, men är detta också fallet i denna situation?
Jag har en metod i t skapad inne i den anonyma funktionen och därför trodde jag att det var möjligt. Ser ut så här:
t.disable = function() {
window.document.removeEventListener("keydown", this, false);
}
Varför kan jag inte göra detta?
Finns det något annat (bra) sätt att göra detta?
Bonusinformation; detta måste bara fungera i Safari, därför saknas stöd för IE.
Svar #1
Du kan namnge funktionen som skickas och använda namnet i removeEventListener, som i:
button.addEventListener('click', function eventHandler() {
///this will execute only once
alert('only once!');
this.removeEventListener('click', eventHandler);
});
REDIGERA: Detta kommer inte att fungera om du arbetar i strikt läge ("use strict";)
REDIGERA 2: arguments.callee är nu föråldrad (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee)
Svar #2
Jag tror att det är poängen med en anonym funktion, den saknar ett namn eller ett sätt att referera till den.
Om jag var du skulle jag bara skapa en namngiven funktion, eller lägga den i en variabel så att du har en referens till den.
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);
Du kan sedan ta bort det genom att
window.document.removeEventListener("keydown", handler);
Svar #3
En version av Otto Nascarellas lösning som fungerar i strikt läge är:
button.addEventListener('click', function handler() {
///this will execute only once
alert('only once!');
this.removeEventListener('click', handler);
});
Svar #4
i moderna webbläsare kan du göra följande...
button.addEventListener( 'click', () => {
alert( 'only once!' );
}, { once: true } );
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters
Svar #5
Det finns ett nytt sätt att göra detta som stöds av de senaste versionerna av de mest populära webbläsarna med undantag för Safari.
Kolla caniuse för uppdaterat stöd.
Uppdatering: Nu stöds det även av Sefari (version 15^).
Vi kan lägga till ett alternativ till addEventListener som heter signal och tilldela en signal från en AbortController på vilken du senare kan anropa abort()-metoden.
Här är ett exempel.
Vi skapar en AbortController:
const controller = new AbortController();
Sedan skapar vi eventListner och skickar in alternativet signal:
document.addEventListener('scroll',()=>{
// do something
},{signal: controller.signal})
Och sedan, för att ta bort eventListner vid ett senare tillfälle, anropar vi:
controller.abort()
