3

Background

I often use the module pattern to organize my code, so that functions and constants operate on a need-to-know basis. If CONSTANT or someFunc are only used by anotherFunc, then I enclose the definition of anotherFunc in an anonymous function, so that the former two don't pollute the global scope. This helps to avoid name clashes and can also give you assurance looking at the code later of what depends on what.

This strategy does create many closures though, and I'm wondering if it might be better for performance (and more maintainable too) to pass in those dependencies explicitly. I think this has the effect of minimizing the scope chain that the function must walk to find variables.

Just to allow feedback on the module pattern itself, I've included three versions: 1) without the module pattern, 2) with it, 3) with it and scope chain minimization.

Without module pattern

var SHARED_CONSTANT;
var SOME_CONSTANT = 5;
var INNER_CONSTANT = {};
var inner = function(y) {
    return y !== {};
};
var outer = function g (x) {
    doSomething();
    $(...).load(inner);
};

With module pattern, but no scope chain minimization

var SHARED_CONSTANT;
var outer = (function() {
    var SOME_CONSTANT = 5;
    var inner = (function() {
        var INNER_CONSTANT = {};
        return function /* inner */ (y) {
            return y !== {};
        };
    }());
    return function /* outer */ (x) {
        doSomething();
        $(...).load(inner);
    };
}());

With module pattern and scope chain minimization

var SHARED_CONSTANT;
var outer = (function($, SHARED_CONSTANT) {
    var SOME_CONSTANT = 5;
    var inner = (function(SOME_CONSTANT, SHARED_CONSTANT) {
        var INNER_CONSTANT = {};
        return function /* inner */ (y) {
            return y !== {};
        };
    }(SOME_CONSTANT, SHARED_CONSTANT));
    return function /* outer */ (x) {
        doSomething();
        $(...).load(inner);
    };
}(jQuery, SHARED_CONSTANT));

Summary

Which version should have better performance (and why)? Is the difference in performance significant? (I.e. is scope chain lookup expensive?) What about memory usage? (I.e. by passing in variables, I'm essentially duplicating scope, right?)

Chris Middleton
  • 5,654
  • 5
  • 31
  • 68
  • 3
    Side note: that code can get really hard to read. I would never go more than three functions deep. To the real question, it's premature optimization, don't make your code hard to read unless you have to. That is, you have a known problem or you know your code is going to be in really tight loops – Ruan Mendes Jan 22 '15 at 20:39
  • 3
    By definition, looking something up from a closer scope is cheaper, because it means less traversing the scope chain. How significant is it? I'm not sure. – Madara's Ghost Jan 22 '15 at 20:39
  • @Juan Thanks for the comment - I often have this feeling too, so I'm glad someone else agrees. The tricky thing is balancing readability with keeping definitions as close to use as possible. Just out of curiosity, do you find snippet #2 closer in readability to #1 or #3? (Is it the anonymous functions making it hard to read or more the dependency injection?) – Chris Middleton Jan 22 '15 at 20:43
  • I'd think that the JIT optimizer speeds this up for you, as well. Smells very strongly of premature optimization, and you're likely much better off focusing on readability and maintainability and only come back to this kind of optimization once a performance problem becomes apparent. – Tim Jan 22 '15 at 20:45
  • @Tim You're probably right about it being premature optimization. I wonder also whether the dependency injection improves the readability of the third snippet (by telling you what's local and what's not), or if it's just too unreadable so the DI doesn't help. What do you think? – Chris Middleton Jan 22 '15 at 20:47
  • possible duplicate of [Is a closure for dereferencing variables useful?](http://stackoverflow.com/q/8288664/1048572) – Bergi Jan 23 '15 at 15:03
  • @Bergi That question is about object property chains, not chains of closure contexts. – Chris Middleton Jan 23 '15 at 23:19
  • @AmadeusDrZaius: It seeks to compare the performance of object property lookups with traversing the closure context chain. Maybe it's not well formulated, it was one of my first questions :-) – Bergi Jan 24 '15 at 12:18

1 Answers1

1

These performance tests seem to confirm what I suggested. This is premature optimization.

The tests do not show any clear favorite. For any given browser, your three snippets are close to each other, with the fastest one changing most times that I ran it. In some of the runs, the overly optimized code is even slower.

It may be because of JIT optimizations.

Lesson to learn: Keep your code as readable as possible and worry about optimization where you know you have bottlenecks.

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • Thanks for the clear answer and link. I forgot about jsperf (oops). I've concluded that a balance somewhere between the first two snippets is probably best for readability. – Chris Middleton Jan 23 '15 at 01:36