When JavaScript codebase grows you may wish to break it in modules or packages. The solution is to find a way to create a namespace and put appropriate functions (and possibly variables) inside. Here is a list of options:
Plain objects
p1 = {};
Packages may be hierarchical:
p1.p2 = {};
p1.p3 = {};
p1.p3.util = {};
In the beginning of a file with JavaScript code you initialize the package p1.p2 like this:
if (!p1) {
p1 = {};
}
if (!p1.p2) {
p1.p2 = {};
}
Placing stuff in package is simple: you just add properties to the package object. For example function kaboom() and var _boomer are defined like this:
p1.p2.kaboom = function(what, who) { what.boom(who); };
p1.p2._boomer = "Gordon Freeman";
And you refer to them accordingly:
p1.p2.kaboom(new Citadel(), p1.p2._boomer);
Common prototype
Same as plain package objects but now there is a function that creates them. The benefit is that you may add meta-functions to packages for introspection. For example you may stick to the policy that packages should contain only functions; you may implement it like this:
function Package() {
};
Package.prototype.validatePackage = function() {
for (obj in this) {
if (!$.isFunction(obj)) {
throw new Error();
}
}
};
p1 = new Package();
// add content to p1...
p1.validatePackage();
Package closures
You create them like this:
p1 = function() {
var cookie = 10;
this.total = function(price) {
return price * cookie;
};
}();
And use as package objects:
var income = p1.total(23);
Package functions
Since functions have names you may use them to represent packages:
function p1() {};
p1.p2 = function() {};
p1.box = [];
p1.p2.add = function(item) {
p1.box.push(item);
};
And the winner is...
Package functions look strange; I don't see any benefits over package objects (at least for now).
Package closures are nice and allow package-private stuff but limited to a single file. You may add content as object properties from other files but then you have to ensure that these files are loaded after the package is available, you can't access package-private stuff and you can't use only a part of the package content (you should always include the file that creates the closure even if you need only one function from those 'other files'). And you may create closures for shared data without using package:
p1 = {};
function() {
var counter = 1;
p1.inc = function() { counter++; };
p1.dec = function() { counter--; };
}();
So there is no real advantage of package closures over the plain package objects.
Package objects with the same prototype may look better than just plain package objects: they give you the control over all packages without any overhead; but do you really need this control? Actually you have to define the Package() function somewhere and ensure that all packages are created by it, but this is a minor complication.
I think that the plain package objects should be enough to construct package hierarchies. If you have a strong use-case for package introspection though, you could consider creating package objects with the same prototype.






