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

jos*_*erk 49 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() {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到this.initialize设置一个单击处理程序this._onClickNavigation.有些人可能希望事件处理程序中的this引用ScrollBanner实例,但遗憾的是它没有.它指的是触发click事件的元素,在本例中为span#banner1-nav

什么是得到的最好方式指的ScrollBanner类的实例?

Fel*_*ing 87

旧/传统方式:

捕获this变量:

this.initialize = function(selector) {
    var that = this;
    $('span#banner1-nav').click(function(event) {
       that._onClickNavigation(event);
    });
}
Run Code Online (Sandbox Code Playgroud)

您还可以分配this给变量,例如instance:

function ScrollBanner() {
    var instance = this;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

并参考instance而不是this所有的电话.

总体思路是存储this在更高范围的变量中.


ECMAScript5方式:

ECMAScript5引入了一个新的函数属性:.bind().MDC的文档显示了不支持它的浏览器的实现.有了它,您可以将某个上下文绑定到一个函数:

this.initialize = function(selector) {
    $('span#banner1-nav').click(this._onClickNavigation.bind(this));
}
Run Code Online (Sandbox Code Playgroud)

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

请注意,这与apply或不同call.这两个都设置上下文执行函数,而bind只设置上下文而不执行函数.


jQuery方式:

jQuery提供了一个$.proxy()相同的方法:

$('span#banner1-nav').click($.proxy(this._onClickNavigation, this));
Run Code Online (Sandbox Code Playgroud)

  • 这非常有用,但感觉很脏.:) (2认同)