Javascript"this"被事件监听器覆盖

luk*_*ell 4 javascript oop events

我可能做错了但是在尝试将一些面向对象的编程应用于Javascript时我发现了一些有趣的行为.考虑以下

function Bug(element) {
    this.focusedCell = null;
    element.addEventListener('click', this.onClick, true);
};

Bug.prototype.onClick = function(event){
    console.log("this is: ");
    console.log(this);
};
Run Code Online (Sandbox Code Playgroud)

当我从控制台调用该方法时,我看到了正确的"this"实例,但当我单击文档中的元素时,我看到文档元素代替实例.所以...使用实例方法的事件监听器可能不是一个好主意,至少我正在这样做.

所以问题是:

  • 有没有像这样的事件监听器调用javascript对象的实例方法,同时保留调用中的实例?

  • 这样做有更好的模式吗?

编辑:除了Chrome之外,我还没有尝试过这个.但我会想象行为是一样的.

小智 6

有一个更好的模式,并不需要太多的变化.我将首先显示代码.

function Bug(element) {
    this.focusedCell = null;
    // --------------------------------v----pass the object, not a function
    element.addEventListener('click', this, true);
};

// Implement the `EventListener` interface
Bug.prototype.handleEvent = function(event) {
    if (event.type === "click")
        this.onClick(event);
}

Bug.prototype.onClick = function(event) {
    console.log(JSON.stringify(this));         // '{"focusedCell":null}'
    console.log(event.currentTarget.nodeName); // "DIV"
};
Run Code Online (Sandbox Code Playgroud)

通过添加handleEvent方法,我们Bug实现了EventListener接口.这允许我们将新Bug对象作为第二个参数传递给addEventListener()而不是函数.

现在,当"click"事件发生时,.handleEvent()将调用该方法,并且该this方法中的值将Bug是绑定的对象.


由于this是对Bug实例的引用,它显然不再是对元素的引用.但它没有必要,因为元素可以通过event.currentTarget.

当然,Bug如果需要,您可以在构造函数中将元素直接添加到对象中.

演示: http : //jsfiddle.net/CnZTa/


  • 我希望我能不止一次地眯起眼睛. (2认同)
  • [此处的代码](http://www.thecssninja.com/javascript/handleevent)可用于提供与旧版浏览器的兼容性. (2认同)

bfa*_*tto 5

您可以使用Function.prototype.bind创建一个绑定到任何一个监听这个你要值:

function Bug(element) {
    this.focusedCell = null;
    element.addEventListener('click', this.onClick.bind(this), true);
};
Run Code Online (Sandbox Code Playgroud)

较旧的(非ES5)浏览器需要填充,例如来自MDN的填充.