Consider the following example:
class Test {
constructor() {
this.x = 42;
}
someMethod() {
console.log(this.x);
}
}
testBtn.x = -42;
var TestInstance = new Test()
testBtn.addEventListener('click', TestInstance.someMethod);
<button id="testBtn" type="button">Click me</button>
Clicking the button will log -42
to the console.
I know I can fix this by explicitly binding TestInstance
to the event handler reference:
class Test {
constructor() {
this.x = 42;
}
someMethod() {
console.log(this.x);
}
}
testBtn.x = -42;
var TestInstance = new Test()
testBtn.addEventListener('click', TestInstance.someMethod.bind(TestInstance));
<button id="testBtn" type="button">Click me</button>
The downside of this being that I can no longer remove that event listener.
I know this can be fixed, too:
class Test {
constructor() {
this.x = 42;
this.someMethod = this._someMethod.bind(this);
}
_someMethod() {
console.log(this.x);
testBtn.removeEventListener('click', this.someMethod);
}
}
testBtn.x = -42;
var TestInstance = new Test()
testBtn.addEventListener('click', TestInstance.someMethod);
<button id="testBtn" type="button">Click me</button>
But this would basically mean that to expose the class API on each method that needs this
to point to the instance, I'd have to create a bound version of that method in the constructor.
Is that the intended way this works, or am I missing a different and hopefully better approach?
Edit: So I'll go with this until the public class field syntax proposal has passed the proposal status:
class Test {
constructor() {
this.x = 42;
const boundMethodNames = ['someMethod'];
boundMethodNames.forEach(method => this[method] = this[method].bind(this));
}
someMethod() {
console.log(this.x);
testBtn.removeEventListener('click', this.someMethod);
}
}
testBtn.x = -42;
var TestInstance = new Test();
testBtn.addEventListener('click', TestInstance.someMethod);
<button id="testBtn" type="button">Click me</button>