views:

585

answers:

6

Does the placement of a function have an effect on the performance of closures within scope? If so, where is the optimal place to put these functions? If not, is the implied association by closure enough reason to place a function in another place logically?

For instance, if foo does not rely on the value of localState, does the fact that localState is accessible from foo have implications as to foo's execution time, memory use, etc.?

(function(){
    var localState;

    function foo(){
        // code
    }

    function bar(){
        // code
        return localState;
    }
})();

In other words, would this be a better choice, and if so why?

(function(){
    function foo(){
        // code
    }

    var localState;

    function bar(){
        // code
        return localState;
    }
})();

Darius Bacon has suggested below that the two samples above are identical since localState can be accessed anywhere from within the block. However, the example below where foo is defined outside the block may be a different case. What do you think?

function foo(){
    // code
}

(function(){

    var localState;

    function bar(){
        // code
        foo();
        return localState;
    }
})();
+1  A: 

The scope of a var or function declaration is the whole block it appears in, regardless of where in the block the declaration is; so it'd be surprising for it to affect efficiency.

That is, it shouldn't matter whether "function foo()" is before or after "var localState" within this block. It may matter whether "function foo()" is in this block or an enclosing one (if it can be hoisted to a higher scope because it doesn't use any local variables); that depends on details of your Javascript compiler.

Darius Bacon
+2  A: 

I don't think there would be any performance overhead, as java script doesn't use the notion of function stack. It supports lexical scoping. The same state is carried forth across closure calls. On a side note, in your example you don't seem to be executing any statements!

questzen
You're right! I tried to imply some execution with the ""// code"" comments, but apparently was not very clear. Thanks for your answer.
brad
+5  A: 

Both those snippets are equivalent, because they're both defined in the (same) environment of the anonymous function you're creating. I think you'd be able to access localState from foo either way.

That being said... if you have absurd amounts of variables in the environment you're creating, then foo's execution time might be affected, as variable lookups will likely take longer. If there are tons of variables that you no longer use in the function you define foo in, and foo doesn't need them either, then foo will cause them to not be garbage-collected, so that could also be an issue.

Claudiu
In fact, to see that JS does in fact close over unused variables, try this: (function(){var a=1;return function(x){eval(x)}})()("alert(a)") Clearly, the inner function makes no reference to `a`, yet it is available.
ephemient
In contrast, in Perl, sub{my$a=1;sub{eval$_[0]}}->()('print $a'), does not print anything, but sub{my$a=1;sub{$a;eval$_[0]}}->()('$a') does: Perl cares about whether the variable is referenced to determine whether it is closed over.
ephemient
+5  A: 

Dog, I would hope the order of declarations would be something the JavaScript interpreters would abstract away. In any case, if there is a performance difference, it would be so minimal as to make this a poster child for the evils of premature optimization.

Andrew Hedges
Second that. Let's not find more ways to create unreadable code.
Borgar
Word up, Andrew. Even if there were a some hypothetical performance gain, I'd rather see it written in the cleanest and most logical order.
keparo
+2  A: 

Every function in Javascript is a closure. The runtime to resolve a variable's value is only incurred if the variable is referenced by the function. For instance, in this example function y captures the value of x even though x is not referenced directly by y:

var x = 3;
function y() eval("x");
y();
3
WPWoodJr
A: 

In your examples the difference won't really matter. Even if foo is in the global scope you won't have a problem.

However, it's useful to keep in mind that if you use the style of assigning functions to variables to declare your functions the order in which they are declare can become quite a problem.

For a better idea, try the following two examples:

CheckOne();
function CheckOne() {
    alert('check...check one.');
}

CheckTwo();
var CheckTwo = function() {
    alert('check...check two.');
};

The only difference between the second and the first is the style they use to declare their functions. The second one generates a reference error.

Cheers.

coderjoe