views:

255

answers:

6

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).

A: 

See the answers to this question.

Dan Breslau
Wow, that looks ugly :(
Timmy
Why does it look ugly?
meder
@timmy - its a simple module pattern. looks like money to me.
Sky Sanders
1) not ending a statement with a semi-colon, 2) the declaration order matters for the chosen/won approach
Timmy
Lack of semicolons in JavaScript is something you'll need to get used to if you're coming from C++, Java, or similar languages. But in what sense does order declaration matter?
Dan Breslau
@timmy, hmmm... are you asking for guidance or giving it? ;-) All three answers are valid variations on the same theme which is how to define a 'namespace' in javascript.
Sky Sanders
+2  A: 
(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.

meder
so if I wanted to call the "bar" function, how would I do that? window.foo.bar() ?
Timmy
just invoke `foo.bar`. If I didn't expose it through `window.foo` then `foo` would only be accessible inside of that function.
meder
Once you set window.<anything>, you defeat the purpose of using namespaces.
Dan Breslau
@Dan - You don't **have** to expose it, I'm simply demonstrating certain aspects of this.
meder
why not `this.foo=foo`, since `window` is non-standard and you're in the global scope there anyway? For that matter, why not `this.foo = {...` instead of `var foo = {...`?
no
because it's easier to read, more explicit, and more "standard" imo.
meder
Easier to read, maybe. More explicit, not really... what else could `this` be in that situation? More standard it's not, and not to sound rude but your opinion doesn't change the 'standardness' in any way. `this` is a formalized part of ECMAScript, `window` is not. Namespaces are for reusable code e.g. libraries. What if someone wants to reuse the library in WSH or node.js? `window` will break it, `this` will not.
no
@meder -- It's up to you what you put in your answer, of course. But in a demonstration of using namespaces, I'd steer clear of using the window namespace, except to describe it as an antipattern.
Dan Breslau
A: 

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.

Sky Sanders
+1  A: 

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() {...}
    }
})();
Justin Johnson
A: 

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.

no
A: 

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.

Rick