jQuery, confusing sample code and elegance Written on March 13, 2011, by danbrown.
Have you ever found a cool snippet of code that does almost what you need, tried to tweak it but it is formatted in such a way that you can’t work out what the hell it is doing?
I’ve noticed this so often recently I thought I’d try and steer people back onto the sanity bandwagon.
Part of writing elegant code is to make it both understandable and easier to debug, re-use and maintain.
The following is a JavaScript example although it can effect any language.
Example
I found the following jQuery code while looking for a 10-20 line example to work with (source - Awesome bubble navigation with jQuery). The sample provides circles with words in and when you mouse over them they grow like bubbles to contain a contextual menu for that word.
note.
The actual code is fine and does what it is supposed to. It is only the obfuscated layout that I am talking about here and even this isn’t too severe. I certainly don’t want to pick on the author. It is also a very nice effect and probably useful to a lot of people. She has a lot of other shiny jQuery stuff on that site so go take a look!
<script type="text/javascript">
$(function() {
$('#nav > div').hover(
function () {
var $this = $(this);
$this.find('img').stop().animate({
'width' :'199px',
'height' :'199px',
'top' :'-25px',
'left' :'-25px',
'opacity' :'1.0'
},500,'easeOutBack',function(){
$(this).parent().find('ul').fadeIn(700);
});
$this.find('a:first,h2').addClass('active');
},
function () {
var $this = $(this);
$this.find('ul').fadeOut(500);
$this.find('img').stop().animate({
'width' :'52px',
'height' :'52px',
'top' :'0px',
'left' :'0px',
'opacity' :'0.1'
},5000,'easeOutBack');
$this.find('a:first,h2').removeClass('active');
}
);
});
</script>
You can work out how it works but you shouldn’t have to. It should tell you.
Looking once or twice isn’t going to be too much of a hassle. Working on code for a few hours though and you will want something more.
It isn’t immediately obvious for example that the two big anonymous functions in there are actually parameters to the same function. Adding comments would have made it worse rather than helping. Also changing some of the values for timing involves having to search for them.
By splitting the anonymous functions into named functions and the values into variables it becomes far more obvious what is going on -
<script type="text/javascript">
var hoverState = {'width' :'199px',
'height' :'199px',
'top' :'-25px',
'left' :'-25px',
'opacity' :'1.0'};
var unHoverState = {'width' :'52px',
'height' :'52px',
'top' :'0px',
'left' :'0px',
'opacity' :'0.1'};
var fadeInTime = 700;
var fadeOutTime = 500;
var growTime = 500;
var shrinkTime = 5000;
function FadeInMenu()
{
$(this).parent()
.find('ul')
.fadeIn(fadeInTime);
}
function HoverStart()
{
var $this = $(this);
$this.find('img')
.stop()
.animate(hoverState, growTime, 'easeOutBack', FadeInMenu);
$this.find('a:first,h2')
.addClass('active');
}
function HoverEnd()
{
var $this = $(this);
$this.find('ul')
.fadeOut(fadeOutTime);
$this.find('img')
.stop()
.animate(unHoverState, shrinkTime, 'easeOutBack');
$this.find('a:first,h2')
.removeClass('active');
}
function AddEvents()
{
$('#nav > div').hover(HoverStart, HoverEnd);
}
$(document).ready(AddEvents);
</script>
The timings and size settings can now be very easily tweaked in one place, the code flow is more obvious and how it effects the DOM is much clearer. I have expanded the final line from the jQuery “document ready” shorthand to show the intent clearer.
The AddEvents function isn’t strictly necessary here as there is only one event, but as there is often more than one thing on a page it sets it up nicely for that. If you add another event for something else you want to avoid the temptation to just jam it in an anonymous function on the document ready part.
Why bother?
So you aren’t writing code to be seen and as long as it works, why should you care?
If you can write that first version of the code perfectly first time with no typos, bugs, or missing brackets, and nobody will need to ever edit it again then fine, go for it. If you are like the other 99.9% of us however it will make your life easier.
- You can find and tweak the parameters without having to care how code itself works.
- You can develop and test the functions in isolation rather than the entire thing in one go.
- You can spend less time debugging.
- You can change it more easily to match any changed HTML structure.
- You can reuse functions in other variations or different effects on the same page.
- You can put the functions in a .js file and reuse the entire effect on other pages.
- You can share it with friends, colleagues or on your site itself and expect they will be able to understand what is going on.
- You can add comments for either while you are developing or for when you come back at a later date.
- You can let other people see your code without embarrassment. e.g job interviews!
- You can develop much more complicated effects and still have a chance to keep things straight in your head.
Size
The new version is longer than the old one (1267 bytes vs. 839) and would be longer still with comments.
This is quite often the case with making things readable. However I don’t consider it an issue. Unless you go completely overboard with the comments…
The other JavaScript files (jQuery and the easing add-on) are over 37k alone and the whole (simple) demo page is 148.9k. A few extra kilobytes for the benefits it gives is a fantastic tradeoff. Moving the functions to a separate .js file would let the browser cache it anyway. A lot of the extra size is spaces for indenting so you can always minify it or use tabs (bleugh!) to save even more.
Conclusion
Anonymous functions are not evil. But they have a place, and “everywhere you can jam one in” isn’t it!
I think part of the problem is that the jQuery API reference uses them for single line demos. The more new programmers see code written that way, the more they will think it is the correct way.
If you don’t already do this, give it a try the next time you write something and see if it speeds up your coding. You have nothing to lose and everything to gain. Let me know in the comments below how it goes!
Read more from the Coding, JavaScript, jQuery, Rant, Webdev category. If you would like to leave a comment, click here: Comment. or stay up to date with this post via RSS, or you can
Trackback from your site.
Social Bookmark :
Technorati,
Digg,
de.licio.us,
Yahoo,
Blinkbits,
Blogmarks,
Google,
Magnolia.
Leave a Comment
If you would like to make a comment, please fill out the form below.

