4

I've started using the Module pattern in a project of mine. As I understand it, it goes something like this:

var obj = (function(foo){
     //Some initialization logic up here.

     //Private methods
     var privateBazz = function(){
         return "I'm known only to this closure!";
     }();

     //Public methods
     return { 
         publicFoo: foo,
         publicBar: function(){
             return foo + privateBazz;
         }
     }
})();

This looked pretty good on paper and, in practice, seems to work reasonably well. Initialization logic at the top is intuitive, then private methods, then public.

I've encountered one issue, though. How should I call publicFoo or publicBar from outside the scope of the return statement and inside the scope of obj's function declaration?

My current solution is to do something like:

var obj = (function(foo){
     //Private methods declared early for use.
     var privateBazz = function(){
         return "I'm known only to this closure!";
     }();

     var privateBar = function(){
         return foo + privateBazz;
     };

     //Some initialization logic up here.
     var dependentOnBar = privateBar();

     //Public methods
     return { 
         publicFoo: foo,
         publicBar: privateBar
     }
})();

This works, but suddenly the declarations of my private variables are placed above my objects private property declarations. The problem becomes exacerbated if I attempt to keep the private function declarations as close to the code which first calls them, so I have just been declaring all the private functions I need at the top, then initializing properties afterwards. Again, this works, but I am used to having code as close to the execution point as possible. So, declaring blocks of private functions at the top is really awkward to me. Does anyone else feel this way, or is this something I just need to get over for JavaScript? Are there any steps I should be taking when I see this happening?

2
  • 1
    That's how it works. There's nothing uncommon about it. Just declare everything with var and only return public variables. Commented Jul 31, 2012 at 4:00
  • 1
    You might know it already, but just in case, here you have a great resource on javascript design patterns addyosmani.com/resources/essentialjsdesignpatterns/book It explains the module pattern and derivates, among many others. Commented Jul 31, 2012 at 6:56

3 Answers 3

1

It sounds like you could solve this problem by simply not using object notation to return the module, but rather initialize it and build it as you go. This would go something like this:

var obj = (function(foo){
     var self = {};
     //Some initialization logic up here.

     //Private properties
     var foo = "only accessible within this scope";

     //Private methods
     var privateBazz = function(){
         return "I'm known only to this closure!";
     }();

     //Public Properties
     self.publicFoo = foo;

     //Public Methods
     self.publicBar = function(){
         return foo + privateBazz;
     };

     return self;
})();
Sign up to request clarification or add additional context in comments.

Comments

1

here is my solution: if you declare everything before the return as a "private" method and make public those you want to, then you can call your private from within the public and vice versa (in your first sample, your privates can't call the publics as they are not declared at that moment)

var obj = (function() {
    // All functions now have direct access to each other
    var privateFunc = function() {
        return "private "+publicFunc1();
    };

    var publicFunc1 = function() {
        return "public 1 ";
    };

    var publicFunc2 = function() {
        return "public 2 "+publicFunc1();
    };


    var publicFunc3 = function() {
        return "public 3 "+privateFunc();
    };

    // Return the object that is assigned to Module
    return {
        publicFunc1: publicFunc1,
        publicFunc3: publicFunc3,
        publicFunc2: publicFunc2
    };
}());

alert(obj.publicFunc3());

Comments

0

If you emulate CommonJS Modules, you can assign properties to the exports object as well as accessing them from elsewhere within the IIFE scope via qualified or unqualified name.

(function (exports, undefined) {
    var priv1 = 42;
    exports.pubOne = function () {};
    var localAlias = function () {};
    localAlias(42);
    exports.pubTwo = localAlias;
})(window.App);

In this example, Window.App might be my namespaced global object for this module, but you could pass in an empty object or some deeply nested namespace just as easily.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.