I have not yet found a common way on the Internet for creating a namespace in JavaScript.
What's the best way to create a namespace (and please list any downfalls that particular approach might have).
I have not yet found a common way on the Internet for creating a namespace in JavaScript.
What's the best way to create a namespace (and please list any downfalls that particular approach might have).
(function() {
var usefulVariable;
var foo = {
bar:function(){ alert('hi') }
};
// leak into global namespace
window.foo = foo;
})();
Only foo
is exposed to the global namespace, and it "lives" within your private self executing anon function namespace.
In JavaScript, namespaces can only be achieved through object literals, which can be as simple as this:
var MyNS = {
f1: function() {...},
f2: function() {...}
};
As others have attempted to show, if you want to provide a private scope within your namespace (which is suggested), the following method is the most appropriate:
var MyNS = (function() {
var private1 = "...",
private2 = "...";
return {
f1: function() {...},
f2: function() {...}
}
})();
The book Pro JavaScript Design Patterns (Harmes & Diaz, 2008) provides examples of namespace creation using simple object literals or self-executing anonymous functions, both of which are illustrated in Justin Johnson's excellent answer, and these approaches work well.
Depending on the situation, it might be possible that the namespace already exists and contains members. In such a case, these approaches would destroy any members in the namespace. If this is a concern, one can use an approach similar to this to preserve any existing members, while adding new ones:
var myNamespace = (function(ns) {
ns.f1 = function() { ... };
ns.f2 = function() { ... };
return ns;
})(window.myNamespace || {});
Here, myNamespace is assigned the value returned by the anonymous, self-executing function that receives the parameter ns. As one can see, the value of this parameter is either window.myNamespace or an empty object, depending on whether or not myNamespace has been previously declared.
To share code between scripts, you have to have at least one global variable (unless of course if you would want to do something as silly as appending your variables to an already existing object such as window.Object
.
Even if you use the module pattern, you need to have a common place to share code, so, say e.g. you have three scripts:
Then we can in the core.js
script file have a module:
(function(global) {
var coreModule = {};
var MY_CONSTANT = 42
var meaningOfLife = function() {
return MY_CONSTANT;
};
coreModule.meaningOfLife = meaningOfLife;
global.myRootNamespace = coreModule;
}(this));
in the utils.js
:
(function(root) {
var utilsModule = root.utils = {};
utilsModule.bark = function() {
console.log("WOOF!");
};
}(myRootNamespace));
Here, we see the use of the augmentation module pattern, and namespacing the functionality depending on the nature of the functionality. This specific implementation overwrites the value of the utils
property on the myRootNamespace
object. However, we can write it so that it does not:
(function(root) {
var utilsModule = root.utils = root.utils || {};
utilsModule.bark = function() {
console.log("WOOF!");
};
}(myRootNamespace));
If one doesn't want to use the module pattern, we can use a simple function to define namespaces for us in a non destructive manner:
var ensureNamespace = function recur(ns, root) {
var parts = typeof ns === 'string' ? ns.split('.') : ns;
var r = root || this;
if (parts[0]) {
var next = parts.shift()
r[next] = r[next] || {};
return recur(parts, r[next]);
}
return r;
};
// maybe another file:
(function(){
var baz = ensureNamespace("foo.bar.baz");
// baz === window.foo.bar.baz;
baz.qux = "Yep...";
}());
see this excellent article for more insight.
Here's my favorite way. It's a little unorthodox but it works well.
var MyNamespace = new function(){
this.MY_CONST_ONE = 1;
this.MY_CONST_TWO = 2;
this.MyClass = function (x) {
this.x = x;
}
this.MyOtherClass = function (y) {
this.y = y;
}
} // end of namespace
// ...
var oc = new MyNamespace.MyOtherClass(123);
The interesting thing about it is the closure function is called with new
instead of the normal parenthesis, so directly inside of it this
refers to the object returned by the function, in other words, the 'namespace' itself.
I generally try to keep it simple and create a global object representing the namespace. If you are using multiple scripts, each declaring the namespace because they might each be used in different applications, then you would probably want to check if the object already exists.
//create the namespace - this will actually obliterate any pre-existing
//object with the same name in the global namespace
//(and this does happen).
//NB ommiting the var keyword automatically chucks the object
//variable into the global namespace - which ordinarily you
//don't want to do
MyNameSpace = {};
//and then create a class/object in the namespace
MyNameSpace.MyClass = {
someProperty: function(){
//do something
},
anotherProperty: function(){
//doing something else
}
};
This is pretty much what everyone else is saying. I'm just giving the really simplistic approach. Main drawback I see is that theoretically the "MyNameSpace" object could already exist - so might want to check that before you create it. Generally, if I'm going to be doing anything more complicated than that I would start thinking of a framework like JQuery or ExtJS which take a lot of pain out of these sort of things.
One more note. Part of the reason why you can't find a common way to do many things in Javascript, like creating namespaces, is that there is always more than one way to skin a cat in Javascript. Most languages are quite proscriptive on how you do things - create classes, are functional or object oriented or procedural. Javascript, on the other hand, is short of keywords and highly flexible. This maybe a good thing or a bad thing - depending on your point of view. But I quite like it.
I believe the module pattern has shown that it is the way to go. Object Literal Name-spacing exposes everything to the caller code outside the namespace which is essentially not a very good idea.
If you insist on creating Object Literal Namespaces, read this tutorial. I find it easy and short and I believe is very through:Object Literal Namespace (OLN) in Javascript
You can combine the answers you have received so far and accomplish much;
var Foo; // declare in window scope.
(function(){
var privateVar = "BAR!";
// define in scope of closure where you can make a mess that
// doesn't leak into the window scope.
Foo = {
staticFunc: function(){ return privateVar; }
};
})();
I generally avoid window.xxxx = yyyy;
as it does not always play nicely with visual studio intellesense. There may be other issues but none that I know of.