After becoming slightly uncomfortable with multiple calls to the same function, with different parameters (as shown in the dom ready section of the code below), I decided to test out passing the parameters for this function by iterating through an array instead (as shown in mouse_function_two). To my surprise I found that mouse_function_two ran considerably faster.
My question is, would mouse_function_two be considered better JavaScript practice than mouse_function_one?
Note: I am slightly concerned I may not be using firebugs console.time utility correctly!
Initial attempt
function mouse_function_one (hover_selector, class_name, add_link) {
hover_item = $(hover_selector)
hover_item.each(function(){
$(this).hover(
function () {
$(this).addClass(class_name);
if ( add_link == true ) {
$(this).click(function(){
var href = $(this).find('a').attr('href');
window.location.href = href;
});
}
else return false;
},
function () {
$(this).removeClass(class_name);
});
});
}
Second (faster) attempt:
function mouse_function_two (args) {
for (var i=0; i < args.length; i++) {
hover_selector = $(args[i][0]);
class_name = args[i][1];
add_link = args[i][2];
hover_item = $(hover_selector)
hover_selector.each(function(){
$(this).hover(
function () {
$(this).addClass(class_name);
if ( add_link == true ) {
$(this).click(function(){
var href = $(this).find('a').attr('href');
window.location.href = href;
});
}
else return false;
},
function () {
$(this).removeClass(class_name);
});
});
}
}
Client code:
// on dom ready
$(function(){
console.time('f1');
mouse_function_one('#newsletter .right', 'hovered', true);
mouse_function_one('.block-couple div.right', 'hovered', false);
mouse_function_one('.bulletin', 'selected', true);
console.timeEnd('f1'); //speed is calculated as 104ms
args = [];
args[0] = ['#newsletter .right', 'hovered', true];
args[1] = ['.block-couple div.right', 'hovered', false];
args[2] = ['.bulletin', 'selected', true];
console.time('f2');
mouse_function_two(args);
console.timeEnd('f2'); //speed is calculated as 10ms
});
If the second routine is faster, it’s probably because it doesn’t do what it is supposed to do. Have a look at this snippet:
Two problems here:
Either of these would cause the same bug, together they just make it doubly certain that it will occur: the closures created for the
hover()event handler functions contain only the values of the final loop iteration. When these handlers are finally called,class_namewill always be"selected", andadd_linkwill always betrue. In contrast, your original function would be called with a different set of parameters each time, which would be captured in the function’s scope by the event handlers, and consequently work as expected.As for the style… It’s messy. You’ve encased the entire function body in a loop, removed descriptive arguments, and greatly complicating the calling of the function.
Fortunately, you can address the issue I point out above, simplify the function, and simplify how it is called all in one go:
You’d then call this new routine like so:
Note that these changes may very well eliminate any speed difference from your initial attempt, as the code effectively does the very same thing, but with the additional step of packing and then extracting parameters…