如何将 this 上下文传递给事件处理程序?
Posted
技术标签:
【中文标题】如何将 this 上下文传递给事件处理程序?【英文标题】:How do I pass the this context into an event handler? 【发布时间】:2011-07-26 07:34:53 【问题描述】:我知道这个问题没有多大意义,但让我试着澄清一下。
我有一个类,叫做 ScrollBanner,它看起来有点如下(为简洁起见,省略了很多):
function ScrollBanner()
this.initialize = function(selector)
$('span#banner1-nav').click(this._onClickNavigation);
this._onClickNavigation = function(event)
this.restartTimer(); // this == span#banner1-nav element from this.initialize
//...
this.restartTimer()
//...
如您所见,this.initialize 将点击处理程序设置为 this._onClickNavigation。有些人可能希望事件处理程序中的 this 引用 ScrollBanner 实例,但遗憾的是它没有。它指的是触发点击事件的元素,在本例中为 span#banner1-nav
让 this 引用 ScrollBanner 类实例的最佳方法是什么?
【问题讨论】:
【参考方案1】:旧的/传统的方式:
在变量中捕获this
:
this.initialize = function(selector)
var that = this;
$('span#banner1-nav').click(function(event)
that._onClickNavigation(event);
);
您还可以将 this
分配给变量,例如instance
:
function ScrollBanner()
var instance = this;
// ...
并在所有调用中引用instance
而不是this
。
总体思路是将this
存储在更高范围的变量中。
ECMAScript5 方式:
ECMAScript5 引入了一个新的函数属性:.bind()
。 MDC's documentation 显示了不支持它的浏览器的实现。有了它,您可以将某个上下文绑定到一个函数:
this.initialize = function(selector)
$('span#banner1-nav').click(this._onClickNavigation.bind(this));
但在幕后它正在做同样的事情。优点是您可以使用支持的浏览器中的内置功能。
请注意,这与 apply
或 call
不同。这两者都设置了上下文并执行函数,而bind
只设置上下文而不执行函数。
jQuery方式:
jQuery 提供了一个方法$.proxy()
做同样的事情:
$('span#banner1-nav').click($.proxy(this._onClickNavigation, this));
【讨论】:
好电话,我通常习惯在我的构造函数顶部分配一个var that = this
,所以你总是可以参考它。然后一直使用that
,以免混淆(当然假设你引用的是那个,而不是其他的)
这很有用,但感觉很脏。 :)
@JoeZephyr:就是这样 ;) 请也看看我的更新。
jQuery 没有跨浏览器兼容的 bind() 函数吗?
@JoeZephyr:对,我忘了。 jQuer 有$.proxy
:api.jquery.com/jQuery.proxy 至少你现在知道所有可能的方法了;)【参考方案2】:
我知道这是一个老问题,但我看到,在 cmets 中,提到了 $.proxy()。是的,它确实会更改对象的上下文,但不会更改 jQuery 事件。
$('.selector').click( $.proxy( function()
console.log(this); /* this is set to .selector */
, this));
$.proxy() 返回this
引用的范围内的函数,但随后该函数被click()
返回并使用,然后将范围更改为.selector
元素。
我在一分钟前测试过,如果我弄错了,请告诉
【讨论】:
不确定这在旧 jQuery 版本中是否有所不同,但这个例子表明你错了:jsfiddle.net/mazztgc9。以上是关于如何将 this 上下文传递给事件处理程序?的主要内容,如果未能解决你的问题,请参考以下文章