I am trying to use the vanilla JS event system to send events between different components of my browser application (no NodeJS involved), by dispatching events to the window object.
// method in Class A
sendDone() {
window.dispatchEvent(new Event('done');
}
In another class, I have a method which handles the optional listener to this event, which can be enabled/disabled by the user.
// method in Class B
setOption(shouldListen) {
if (shouldListen) {
window.addEventListener('done', this.doneHandler);
} else {
window.removeEventListener('done', this.doneHandler);
}
}
However, the handler gets the window context instead of the instance context, and the this keyword doesn't work as I would like it to:
// method in Class B
doneHandler() {
this.someMethod(this.someValue); // doesn't work
}
I can't pass this to the handler with an anonymous function, because I can't remove an anonymous function from the listeners list. For the same reason, I can't include the handler code inside the function definition, like this:
const self = this;
window.addEventListener('done', function() {
// can use self here instead
// but listener still can't be removed
});
I'm new to JS and I'm wondering how this sort of scenario is usually handled.
Thanks.
CodePudding user response:
You need to use Function.prototype.bind() in the constructor of your class:
constructor() {
this.doneHandler = this.doneHandler.bind(this);
}
The rest of the code won't change, so now you can add and remove the event listener.
CodePudding user response:
Use bind() to explicitly set this inside the this.doneHandler and to be able to remove the event listener, save the reference to the function in created as a result of calling bind.
// save a reference to the bound function
this.handler = this.doneHandler.bind(this);
// pass the bound handler function
if (shouldListen) {
window.addEventListener('done', this.handler);
} else {
window.removeEventListener('done', this.handler);
}
