在javascript原型事件处理程序中保留'this'引用

时间:2011-11-11 21:56:14

标签: javascript oop event-handling this

在对象原型中存储的事件处理程序中保留this javascript引用的正确方法是什么?我想远离创建像'_this'或'that'这样的临时变量,我不能使用像jQuery这样的框架。我看到很多人谈论使用'绑定'功能但不确定如何在我给定的场景中实现它。

var Example = function(foo,bar){
    this.foo = foo;
    this.bar = bar;
};
Example.prototype.SetEvent = function(){
    this.bar.onclick = this.ClickEvent;
};
Example.prototype.ClickEvent = function(){
    console.log(this.foo); // logs undefined because 'this' is really 'this.bar'
};

4 个答案:

答案 0 :(得分:22)

到目前为止,我发现bind()是最干净的解决方案:

this.bar.onclick = this.ClickEvent.bind(this);

顺便说一句,其他 this按照惯例被称为that

答案 1 :(得分:7)

bindhttps://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

上查看MDN文档

使用此功能,您可以更改范围(this是什么):

Example.prototype.SetEvent = function(){
    this.bar.onclick = this.ClickEvent.bind(this);
};

但请注意,这是EMCA的新增功能,因此可能并非所有用户代理都支持。上面链接的MDN文件中有一个pollyfill。

答案 2 :(得分:5)

bind的问题是only supported by IE9+

该函数可以使用es5-shim进行填充,但它与本机实现不完全相同:

  
      
  • 警告:绑定函数有一个原型属性。
  •   
  • 警告:绑定函数不会太难以阻止您操纵argumentscaller属性。
  •   
  • 警告:绑定函数在callapply中没有检查,以避免作为构造函数执行。
  •   

另一种选择可以是jQuery.proxy

$(elem).on('click', $.proxy(eventHandler, this));

如果你想稍后删除事件处理程序,这会更有帮助,因为当一个函数通过proxy方法时,jQuery会生成一个新的guid值,然后将该guid应用于核心函数作为结果代理函数,以便您可以使用原始函数引用来取消绑定已代理的事件处理程序回调:

$(elem).off('click', eventHandler);

答案 3 :(得分:0)

其他解决方案:使用ES6引入的“箭头功能”。那些具有不改变上下文的特殊性,IE this指向的是什么。这是一个例子:

function Foo(){
    myeventemitter.addEventListener("mousedown", (()=>{
        return (event)=>{this.myinstancefunction(event)}; /* Return the arrow
function (with the same this) that pass the event to the Foo prototype handler */
    })());
}
Foo.prototype.myinstancefunction = function(event){
    // Handle event in the context of your Object
}

Arrow function specs @ MDN

修改

要小心。如果您在客户端使用它并且您无法确定JS解释器的功能,请注意旧浏览器将无法识别箭头功能(see CanIUse stats)。仅当您知道将运行它的内容时才使用此方法(仅限最近的浏览器和NodeJS应用程序)