Javascript ES6 类:在方法上应用“addEventListener”访问“this”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30446622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 05:10:54  来源:igfitidea点击:

ES6 Class: access to 'this' with 'addEventListener' applied on method

javascriptdomecmascript-6dom-events

提问by Yukulélé

In this es6 script, the click event don't works because sayHellomethod is called with this.elm(<div>) as this.

在这个 es6 脚本中,click 事件不起作用,因为sayHello方法是用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);
  }
}

回答by loganfsmyth

This is a general JS issue, but the core of it is that

这是一个普遍的 JS 问题,但它的核心是

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 fnis called that thiswill be set to your desired value. The easiest way to do this in ES5 would be

您正在传递一个函数作为事件处理程序,但没有确保何时fn被调用this将被设置为您想要的值。在 ES5 中执行此操作的最简单方法是

this.elm.addEventListener('click', this.sayHello.bind(this));

or in ES6, using an arrow function:

或者在 ES6 中,使用箭头函数:

this.elm.addEventListener('click', evt => this.sayHello(evt));

Note however that both of these solutions will break your (already slightly broken) logic in killbecause

但是请注意,这两种解决方案都会破坏您的(已经稍微损坏的)逻辑,kill因为

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);