このes6スクリプトでは、sayHello
メソッドがthis.Elm
(<div>
)としてthis
として呼び出されるため、クリックイベントは機能しません。
スコープを失うことなくイベントをメソッドに関連付ける方法
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);
}
}
これは一般的なJSの問題ですが、その中心は
this.Elm.addEventListener('click', this.sayHello);
と違いはありません
var fn = this.sayHello;
this.Elm.addEventListener('click', fn);
関数をイベントハンドラとして渡しますが、fn
が呼び出されたときに、this
が目的の値に設定されることを保証していません。 ES5でこれを行う最も簡単な方法は
this.Elm.addEventListener('click', this.sayHello.bind(this));
またはES6では、矢印関数を使用します。
this.Elm.addEventListener('click', evt => this.sayHello(evt));
ただし、これらのソリューションは両方ともkill
の(すでに少し壊れている)ロジックを壊すことに注意してください。
this.Elm.removeEventListener('click', /* what? */);
添付した関数への参照はもうないので、イベントハンドラーを削除する方法はありません。
2つのオプションをお勧めします。
// 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);
または
// 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);