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

时间:2022-03-26 05:55:24

I know this question doesn't make much sense, but let me try and clarify a bit.

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

I have a class, called ScrollBanner, and it looks somewhat as follows (a lot omitted for brevity):

我有一个名为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() {
        //...
    }
}

As you can see this.initialize sets a click handler to this._onClickNavigation. Some might expect the this inside the event handler to refer to the ScrollBanner instance, but sadly it doesn't. It refers to the element that trigerred the click event, in this case span#banner1-nav

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

What would be the best way to get this to refer to the ScrollBanner class instance?

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

2 个解决方案

#1


77  

The old/traditional way:

旧/传统方式:

Capture this in a variable:

在变量中捕获它:

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

You could also assign this to a variable e.g. instance:

您也可以将其分配给变量,例如例如:

function ScrollBanner() {
    var instance = this;
    // ...
}

and refer to instance instead of this in all the calls.

并在所有调用中引用实例而不是this。

The overall idea is to store this in a variable in a higher scope.

总体思路是将其存储在更高范围的变量中。


The ECMAScript5 way:

ECMAScript5方式:

ECMAScript5 introduces a new property of functions: .bind(). MDC's documentation shows an implementation for browsers that don't support it. With it you can bind a certain context to a function:

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

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

but behind the scenes it is doing the same thing. The advantage is that you make use of built-in functionality in browser that support is.

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

Note that this is different from apply or call. Both of these set the context and execute the function, whereas bind only sets the context without executing the function.

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


The jQuery way:

jQuery方式:

jQuery provides a method $.proxy() that is doing the same:

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

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

#2


1  

I know this is an old question, but I saw, that in the comments, $.proxy() is mentioned. Yes, it does change the context of an object but not in an jQuery event.

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

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

$.proxy() returns the function in the scope that this reffered but then that function is returned and used by click() which then changes the scope to .selector element.

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

I've tested it a minute ago but if i got it wrong, please, do tell

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

#1


77  

The old/traditional way:

旧/传统方式:

Capture this in a variable:

在变量中捕获它:

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

You could also assign this to a variable e.g. instance:

您也可以将其分配给变量,例如例如:

function ScrollBanner() {
    var instance = this;
    // ...
}

and refer to instance instead of this in all the calls.

并在所有调用中引用实例而不是this。

The overall idea is to store this in a variable in a higher scope.

总体思路是将其存储在更高范围的变量中。


The ECMAScript5 way:

ECMAScript5方式:

ECMAScript5 introduces a new property of functions: .bind(). MDC's documentation shows an implementation for browsers that don't support it. With it you can bind a certain context to a function:

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

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

but behind the scenes it is doing the same thing. The advantage is that you make use of built-in functionality in browser that support is.

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

Note that this is different from apply or call. Both of these set the context and execute the function, whereas bind only sets the context without executing the function.

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


The jQuery way:

jQuery方式:

jQuery provides a method $.proxy() that is doing the same:

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

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

#2


1  

I know this is an old question, but I saw, that in the comments, $.proxy() is mentioned. Yes, it does change the context of an object but not in an jQuery event.

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

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

$.proxy() returns the function in the scope that this reffered but then that function is returned and used by click() which then changes the scope to .selector element.

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

I've tested it a minute ago but if i got it wrong, please, do tell

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