Where should I use private methods when using a JavaScript module template?

I started using the module template in my project. As I understand it, it looks 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; } } })(); 

It looked pretty good on paper and, in practice, seems to work quite well. The initialization logic above is intuitive, then private methods, and then publicly available.

I ran into one problem. How can I call publicFoo or publicBar outside the scope of the return statement and inside the scope of the obj 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 all of a sudden my personal variable declarations are placed over the private property declarations of the objects. The problem will be compounded if I try to keep the declarations of the private function as close as possible to the code that first calls them, so I just declared all the private functions that I need at the top, and then initialized the properties afterwards. Again, this works, but I'm used to having the code as close to the execution point as possible. So, declaring private function blocks at the top is really inconvenient for me. Does anyone else feel like this, or is it just that I just need to get into JavaScript? Are there any steps that I should take when I see this?

+4
source share
3 answers

It looks like you could solve this problem simply by not using object notation to return the module, but rather initialize it and build it along the way. It will look 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; })(); 
+1
source

here is my solution: if you declare everything before returning as the "private" method and publish those you want, then you can call your private individuals from the public and vice versa (in your first example, your privates cannot call the public, because they are not declared in this 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()); 
+1
source

If you emulate CommonJS Modules , you can assign properties to the exports object, as well as access them from another location within the IIFE area through a 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 may be my global object with names for this module, but you can easily and easily pass an empty object or some deeply nested namespace.

0
source

All Articles