In this es6 script, the click event don't works because sayHello
method is called with this.elm
(<div>
) as this
.
how to associate a event to a method without loose the scope?
class player{
constructor (name) {
this.name = name;
this.elm = document.createElement('div');
this.elm.addEventListener('click', this.sayHello);
}
sayHello() {
console.log(this.name + ' say: "hello!"'); // 'undefined say 'hello!"';
}
kill() {
console.log(`RIP ${this.name} :'(`);
this.elm.addClass('dead');
this.elm.removeEventListener('click', this.sayHello);
}
}
This is a general JS issue, but the core of it is that
this.elm.addEventListener('click', this.sayHello);
is no different than
var fn = this.sayHello;
this.elm.addEventListener('click', fn);
You are passing a function as the event handler, but have not ensured that when fn
is called that this
will be set to your desired value. The easiest way to do this in ES5 would be
this.elm.addEventListener('click', this.sayHello.bind(this));
or in ES6, using an arrow function:
this.elm.addEventListener('click', evt => this.sayHello(evt));
Note however that both of these solutions will break your (already slightly broken) logic in kill
because
this.elm.removeEventListener('click', /* what? */);
You don't have any reference to the function that you attached anymore, so you have no way of removing the event handler.
I'd suggest two options:
// Create a new function that is bound, and give it a new name
// so that the 'this.sayHello()' call still works.
this.boundSayHello = evt => this.sayHello(evt);
this.elm.addEventListener('click', this.boundSayHello);
this.elm.removeEventListener('click', this.boundSayHello);
or
// Bind the function with the same name and use `.bind` instead of the
// arrow function option.
this.sayHello = this.sayHello.bind(this);
this.elm.addEventListener('click', this.sayHello);
this.elm.removeEventListener('click', this.sayHello);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With