With one exception - event handling.
Let's take some very simple code to illustrate the problem. The purpose of this code is to force all links to be diverted through a different script. It's overkill, but it illustrates the problem.
function linkRedirect(link_element)In order to get around this, one can use a closure and refer to it instead of this in the event handler callback, like this:
{
this.redirect_base = "http://example.com/redirect?url=";
this.link_element = link_element;
this.link_element.addEventListener("click",
this.handleClick, false);
}
linkRedirect.prototype.handleClick = function(e)
{
e.preventDefault();
// The following will not work
window.location = this.redirect_base
+ escape(this.link_element.getAttribute("href"));
}
Unfortunately, closures can be a great source of memory leaks, especially in Internet Explorer, and are best avoided if possible.
function linkRedirect(link_element)
{
this.redirect_base = "http://example.com/redirect?url=";
this.link_element = link_element;
var closure = this;
this.link_element.addEventListener("click", function(e)
{
e.preventDefault();
closure.execRedirect();
}, false);
}
linkRedirect.prototype.execRedirect = function()
{
window.location = this.redirect_base
+ escape(this.link_element.getAttribute("href"));
}
Mid-way through the development of vBulletin, we came across the Yahoo! User Interface (YUI) library, which wraps all this stuff into one beautiful function, which allows this to be passed as a parameter to the callback:
function linkRedirect(link_element)Isn't that fantastic?
{
this.redirect_base = "http://localhost/~kier/jq/redirect.php?url=";
this.link_element = link_element;
YAHOO.util.Event.on(this.link_element, "click",
this.execRedirect, this, true);
}
linkRedirect.prototype.execRedirect = function(e)
{
e.preventDefault();
window.location = this.redirect_base
+ escape(this.link_element.getAttribute("href"));
}
So why am I writing about this? Well, I've been playing with jQuery and found to my horror that it does not have this scope management system by default, requiring a revertion to the bad old days of closures and helper functions... ugh.
Today, I'm going to attempt to extend jQuery to be able to pass scope parameters in the same way that YUI does. Good luck me...
... and after a couple of hours of investigation, I found that the bleeding-edge version of jQuery in SVN does indeed have scope handling through .bind().
ReplyDelete$(el).bind("click", this.myMethod, this);
Hooray!
Good :)
ReplyDelete