Home > front end >  Add/remove eventListeners while keeping instance context of "this"
Add/remove eventListeners while keeping instance context of "this"

Time:09-23

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