15

I've frequently encountered sites that put all of their JavaScript inside a namespace structure along the lines of:

namespaces = { com : { example: { example.com's data} }

However, setting this up safely with respect to other namespaced frameworks seems to require a relatively hefty amount of code (defined as > 2 lines). I was wondering whether anyone knows of a concise way to do this? Furthermore, whether there's a relatively standard/consistent way to structure it? For example, is the com namespace directly attached to the global object, or is it attached through a namespace object?

[Edit: whoops, obviously {com = { ... } } wouldn't accomplish anything close to what I intended, thanks to Shog9 for pointing that out.]

Stephen King
  • 581
  • 5
  • 18
  • 31
olliej
  • 35,755
  • 9
  • 58
  • 55

8 Answers8

19

Javascript doesn't have stand-alone namespaces. It has functions, which can provide scope for resolving names, and objects, which can contribute to the named data accessible in a given scope.

Here's your example, corrected:

var namespaces = { com: { example: { /* example.com's data */ } } }

This is a variable namespaces being assigned an object literal. The object contains one property: com, an object with one property: example, an object which presumably would contain something interesting.

So, you can type something like namespaces.com.example.somePropertyOrFunctionOnExample and it'll all work. Of course, it's also ridiculous. You don't have a hierarchical namespace, you have an object containing an object containing an object with the stuff you actually care about.

var com_example_data = { /* example.com's data */ };

That works just as well, without the pointless hierarchy.

Now, if you actually want to build a hierarchy, you can try something like this:

com_example = com_example || {};
com_example.flags = com_example.flags || { active: false, restricted: true};

com_example.ops = com_example.ops || (function()
    {
       var launchCodes = "38925491753824"; // hidden / private
       return {
         activate: function() { /* ... */ },
         destroyTheWorld: function() { /* ... */ }
       };
    })();

...which is, IMHO, reasonably concise.

David Underhill
  • 15,896
  • 7
  • 53
  • 61
Shog9
  • 156,901
  • 35
  • 231
  • 235
  • 1
    Although, now `com_example` is going to be part of the global object. Assume we add many more objects `com_something_else`, `com_etc`, then we are still polluting the root level of the global object. Would it not be preferable if we had only one `com` object in global where all other objects were added? Also, we don't want to overwrite any existing objects, what if multiple libraries are being used. – Peter Oct 04 '11 at 05:00
  • 2
    @Peter: if multiple libraries define the same symbols, you're going to have problems no matter what; that's why libraries like jQuery go to such lengths to stuff everything into a single global object. My point wasn't that you *should* use multiple top-level objects, merely that faking namespaces with deeply-nested objects doesn't really buy you anything over crazy-long object names. See my last example for a more practical method: use a single global name that's unlikely to collide, and then a technique that allows disparate bits of code to add objects to it. – Shog9 Oct 04 '11 at 15:39
12

Here was an interesting article by Peter Michaux on Javascript Namespacing. He discusses 3 different types of Javascript namespacing:

  1. Prefix Namespacing
  2. Single Object Namespacing
  3. Nested Object Namespacing

I won't plagiarize what he said here but I think his article is very informative.

Peter even went so far as to point out that there are performance considerations with some of them. I think this topic would be interesting to talk about considering that the new ECMAScript Harmony plans have dropped the 4.0 plans for namespacing and packaging.

Joseph Pecoraro
  • 2,858
  • 1
  • 20
  • 25
6

I try to follow the Yahoo convention of making a single parent object out in the global scope to contain everything;

var FP = {};
FP.module = {};
FP.module.property = 'foo';
Polsonby
  • 22,825
  • 19
  • 59
  • 74
5

To make sure you don't overwrite an existing object, you should so something like:

if(!window.NameSpace) {
    NameSpace = {};
}

or

var NameSpace = window.NameSpace || {};

This way you can put this at the top of every file in your application/website without worrying about the overwriting the namespace object. Also, this would enable you to write unit tests for each file individually.

Ricky
  • 5,365
  • 2
  • 32
  • 30
3

The YUI library library has code which handles namespacing using a function which you may find preferable. Other libraries may do this also.

Brendan
  • 18,771
  • 17
  • 83
  • 114
1

I like also this (source):

(function() {
    var a = 'Invisible outside of anonymous function';
    function invisibleOutside() {
    }

    function visibleOutside() {
    }
    window.visibleOutside = visibleOutside;

    var html = '--INSIDE Anonymous--';
    html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside;
    html += '<br/> typeof visibleOutside: ' + typeof visibleOutside;
    contentDiv.innerHTML = html + '<br/><br/>';
})();

var html = '--OUTSIDE Anonymous--';
html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside;
html += '<br/> typeof visibleOutside: ' + typeof visibleOutside;
contentDiv.innerHTML += html + '<br/>';​
dfa
  • 114,442
  • 31
  • 189
  • 228
1

As an alternative to a dot or an underscore, you could use the dollar sign character:

var namespaces$com$example = "data"; 
Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
  • What benefit does this provide? – eyelidlessness Oct 25 '08 at 04:11
  • By doing it this way, you don't have to define your namespaces as an object with nested inner objects. You can just define the name anywhere. – Mark Cidade Oct 28 '08 at 04:04
  • I still don't see the benefit of using the $ sign instead of a dot or underscore. I think the $ sign makes the word harder to read than a dot or an underscore. – rodrigo-silveira Feb 17 '12 at 21:06
  • I think it's much worse than using nested objects - you have tons of separate variables which - no matter if global or local - will make debugging a hell when you look at the currently defined variables. – ThiefMaster Mar 10 '12 at 11:02
0

Use an object literal and either the this object or the explicit name to do namespacing based on the sibling properties of the local variable which contains the function. For example:

var foo = { bar: function(){return this.name; }, name: "rodimus" }
var baz = { bar: function(){return this.name; }, name: "optimus" }

console.log(foo.bar());
console.log(baz.bar());

Or without the explicit name property:

var foo = { bar: function rodimus(){return this; } }
var baz = { bar: function optimus(){return this; } }

console.log(foo.bar.name);
console.log(baz.bar.name);

Or without using this:

var foo = { bar: function rodimus(){return rodimus; } }
var baz = { bar: function optimus(){return optimus; } }

console.log(foo.bar.name);
console.log(baz.bar.name);

Use the RegExp or Object constructor functions to add name properties to counter variables and other common names, then use a hasOwnProperty test to do checking:

 var foo = RegExp(/bar/);
 
/* Add property */
foo.name = "alpha";

document.body.innerHTML = String("<pre>" + ["name", "value", "namespace"] + "</pre>").replace(/,/g, "&#09;");

/* Check type */
if (foo.hasOwnProperty("name")) 
  {
  document.body.innerHTML += String("<pre>" + ["foo", String(foo.exec(foo)), foo.name] + "</pre>").replace(/,/g, "&#09;");
  }

/* Fallback to atomic value */
else 
  {
  foo = "baz";
  }

var counter = Object(1);

/* Add property */
counter.name = "beta";

if (counter.hasOwnProperty("name")) 
  {
  document.body.innerHTML += String("<pre>" + ["counter", Number(counter), counter.name] + "</pre>").replace(/,/g, "&#09;");
  } 
else 
  {
  /* Fallback to atomic value */
  counter = 0;
  }

The DOM uses the following convention to namespace HTML and SVG Element interface definitions:

  • HTMLTitleElement
  • SVGTitleElement
  • SVGScriptElement
  • HTMLScriptElement

JavaScript core uses prototypes to namespace the toString method as a simple form of polymorphism.

References

Community
  • 1
  • 1
Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265