login
recursive function calls in JavaScript posted: Thu 2013-07-18 17:10:12 tags: tech
Yesterday I left off looking at 3 loopish ways to apply a jQuery effect on each child element contained in a parent element - iconically, all DIVs within a parent DIV, but just as easily, all TRs in a TABLE, all LI elements in a UL, etc. The code in its originally-accepted form was:
(function hidenext(jq){
    jq.eq(0).fadeOut("fast", function(){
        (jq=jq.slice(1)).length && hidenext(jq);
    });
})($('div#bodyContent a'))

So, given a DIV with id=bodyContent, containing an arbitrary number of Anchor elements, this function will iterate through them, fading them out one after the other. I tested it and it works as expected

Why the parentheses around the function declaration? This just cuts a step out of declaring the function, then invoking it. It's equivalent to the following:

function hidenext(jq){
    jq.eq(0).fadeOut("fast", function(){
        (jq=jq.slice(1)).length && hidenext(jq);
    });
}
hidenext($('div#bodyContent a'));

Having combined the declaration and invocation, we can call the function again by name later on. But what if it's an effect we run just once on page-load? Normally it's considered good form to leave one-use functions anonymous, unless you're unrolling some deep-nested code for visual clarity's sake. And once upon a time, there was a JavaScript language construct to permit self-reference in anonymous functions: arguments.callee. But now it's deprecated in the "strict" language spec, in favor of function.caller, except function.caller isn't technically "standard" either (even though it's supported in all major browsers).

(function(jq){
    jq.eq(0).fadeOut("fast", function(){
        (jq=jq.slice(1)).length && arguments.callee(jq);
    });
})($('div#bodyContent a'))

So if you're just going to run it once, there's virtually no performance lost by naming the function. In a reuse scenario, for example where chained effects are used as a click event handler, I'd still declare and define the function up-front rather than defining it self-executing at first invocation.