在此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);
}
}
答案 0 :(得分:92)
这是一个普遍的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? */);
您不再引用您附加的函数,因此您无法删除事件处理程序。
我建议两个选项:
// 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);