Reputation: 12121
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):
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 triggered the click event, in this case span#banner1-nav
.
What would be the best way to get this
to refer to the ScrollBanner
class instance?
Upvotes: 60
Views: 49283
Reputation: 759
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.
$('.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.
I've tested it a minute ago but if i got it wrong, please, do tell
Upvotes: 3
Reputation: 816404
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.
The overall idea is to store this
in a variable in a higher scope.
The ECMAScript5 way:
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:
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.
The jQuery way:
jQuery provides a method $.proxy()
that is doing the same:
$('span#banner1-nav').click($.proxy(this._onClickNavigation, this));
Upvotes: 103