Reputation: 16139
In the last couple of years I've been using JavaScript name spaces espoused by YUI as my default way of formatting JavaScript code.
All in all it works well in more complex environments where many web widgets may be stuck together at different times.
Until recently I've almost always used added event handlers in the HTML by calling the handlers from the name spaced object itself.
I've been using JQuery lately and have been setting the handlers inside of the ready function rather than in the HTML.
As I do more and more of that it seems that the closure of the JQuery ready function is taking the place of the name space object.
What I am ending up with now (at least for one widget/tool type pages) is a name space object that primarily deals holds data and a bunch of closed event handlers that I access the name space object for data specific purposes.
My question is, what are some best practices for dealing with closures verses a Name space object particularly as it relates to event handlers?
Or, similarly, what are some best practices for setting up event handlers, should they be "heavy weight" and handle the processing themselves, or hand off to more library like code.
Personally it's harder to keep track of the flow of many separate "heavy weight" event handlers.
Upvotes: 0
Views: 554
Reputation: 35812
This is a very subjective question. That being said, I'll do my best to give what I think are the pros/cons of each approach.
Namespace Objects:
yourNamespace.events.someClickHandler = function(event) {...}
$(function() {
$("#someElement").click(yourNamespace.events.someClickHandler);
}
One of the first "cons" of this approach is the separation of your event handler from it's hookup. You can avoid this by hooking up each event after it is defined (as I did in the example above), but then you wind up with a whole lot of "$(function() {" lines throughout your code.
Another "con" of this style is the long names for your event handlers (eg. "yourNamespace.events.someClickHandler"). You can use aliases:
var events = yourNamespace.events;
$("#someElement").click(events.someClickHandler);
and shorter namespace names to mitigate this somewhat, but there's really no way to get around it.
So with all those cons, why would anyone use the namespace pattern? Well, one "pro" of it is that the events are accessible. Let's say (for debugging purposes) you want to log the event object that gets passed to your click handler. Using Firebug you could do something like:
var oldHandler = yourNamespace.events.someClickHandler;
var newHandler = function(e) {console.log(e); oldHandler(e);}
$("#someElement").unbind("click");
$("#someElement").click(yourNamespace.events.someClickHandler);
and, without even refreshing the page, you could get your event logged.
Similarly, this style has another pro of re-usability. If you want to make a new click handler that is similar to the old one, but also does x, y, and z, you could do:
yourNamespace.events.advancedClickHandler = function(event) {
yourNamespace.events.someClickHandler(e);
x(); y(); z();
}
Now in contrast we have the "closure" style (I'd prefer to call it the "anonymous function" style).
$(function() {
$("#someElement").click(function(event) {...});
}
It's clearly more concise, the handler's definition is about as close as it can get to the hook-up, and I think it even uses a teeny bit less memory because there's no variable reference. BUT, you won't be able to do any live debugging stuff, you won't be able to hook that handler up anywhere else, or extend it in some new handler, or anything like that, because your handler only exists for the moment when you hook it up.
So, hopefully that helps. In my experience the namespace object style is generally the preferred method, especially the more hardcore/serious the JS project is. But it definitely has some disadvantages; there really is no perfect (ie. perfectly clean/ and re-usable) way of hooking up events in JS at this time.
Upvotes: 2