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

Geo*_*ess 19 javascript oop this event-handling

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'
};
Run Code Online (Sandbox Code Playgroud)

Tom*_*icz 22

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

this.bar.onclick = this.ClickEvent.bind(this);
Run Code Online (Sandbox Code Playgroud)

顺便说一下,另一个 thisthat常规召集.

  • 实际上,我讨厌创建`this`引用,无论它们如何命名.但同意,"那个"不是最好的命名. (5认同)
  • 我*讨厌*创建一个名为"that"(la Crockford)的引用.我更喜欢"实例"(拉斯特凡诺夫)或"我"(拉斯维加斯) (4认同)

Chr*_*ker 7

查看MDN文档bind:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

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

Example.prototype.SetEvent = function(){
    this.bar.onclick = this.ClickEvent.bind(this);
};
Run Code Online (Sandbox Code Playgroud)

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


Pao*_*tti 5

问题bind只有IE9 +支持.

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

  • 警告:绑定函数有一个prototype属性.
  • 警告:绑定函数不要太努力,以免你操纵它们argumentscaller属性.
  • 警告:绑定函数没有检入callapply避免作为构造函数执行.

另一种选择可以是jQuery.proxy:

$(elem).on('click', $.proxy(eventHandler, this));
Run Code Online (Sandbox Code Playgroud)

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

$(elem).off('click', eventHandler);
Run Code Online (Sandbox Code Playgroud)