如何将此上下文传递给事件处理程序?

时间:2011-03-30 18:19:14

标签: javascript javascript-events

我知道这个问题没有多大意义,但让我试着澄清一下。

我有一个名为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

引用 ScrollBanner 类实例的最佳方法是什么?

2 个答案:

答案 0 :(得分:84)

旧/传统方式:

在变量中捕获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));
}

但幕后它正在做同样的事情。优点是您可以在支持的浏览器中使用内置功能。<​​/ p>

请注意,这与applycall不同。这两个设置上下文执行函数,而bind仅设置上下文而不执行函数。


jQuery方式:

jQuery提供了一个方法$.proxy(),它正在做同样的事情:

$('span#banner1-nav').click($.proxy(this._onClickNavigation, this));

答案 1 :(得分:1)

我知道这是一个老问题,但我看到,在评论中,提到了$ .proxy()。是的,它确实改变了对象的上下文,但没有改变jQuery事件。

 $('.selector').click( $.proxy( function() {
     console.log(this); /* this is set to .selector */
 }, this));

$ .proxy()返回this引用的作用域中的函数,然后由click()返回并使用该函数,然后将作用域更改为.selector元素。

我在一分钟前测试过,但如果我弄错了,请告诉