JavaScript Namespacing

There are many ways to safely namespace your objects in JavaScript. This article discusses common practices I have seen.

Prefix Namespacing

If the goal of namespacing is to avoid collisions. The following system is just as likely to avoid namespace collisions as any other system as long as we know the global variable name prefix myApp_ is unique.

// add uniquely named global properties
var myApp_sayHello = function() {
  alert('hello');
};
var myApp_sayGoodbye = function() {
  alert('goodbye');
};

// use the namespace properties
myApp_sayHello();

C programs frequently use prefix namespacing. In the JavaScript world, you may have encountered Macromedia's MM_ functions like MM_showHideLayers.

I think that prefix namespacing is the most clearly understandable namespacing system in JavaScript. (The object namespacing strategies below can cause confusion when the keyword this becomes involved.)

Prefix namespacing does create many global objects. This is not a problem in regard to namespace collisions as the prefix protects against that. The problem with prefix namespacing is some web browsers (e.g. Internet Explorer 6) perform poorly if there are many global objects, so I am told. I ran some tests and there was a little thread on comp.lang.javascript but I didn't peruse this topic completely.

Single Object Namespacing

Currently, the most popular JavaScript namespacing practice is using a single global variable to reference an object. That referenced object then references your "real business" and because your global object is named uniquely then your code should run happily with anyone else's code present.

If you are pretty sure no one in the world has used the global variable name myApp then you may have code like this

// define the namespace object
var myApp = {};

// add properties to the namespace object
myApp.sayHello = function() {
  alert('hello');
};
myApp.sayGoodbye = function() {
  alert('goodbye');
};

// use the namespace properties
myApp.sayHello();

When the the last line of code above runs, the JavaScript interpreter first finds the myApp object, then finds and calls that object's sayHello property.

A problem with object namespacing is it leads to confusion with object-oriented message passing. There is no obvious syntactic difference between

namespace.prop();

and

receiver.message();

Looking at this confusion more carefully we have the following for the namespace concept. Suppose we have the following library.

var myApp = {};

myApp.message = 'hello';

myApp.sayHello = function() {
  alert(myApp.message);
};

The code using this library is free to write.

myApp.sayHello(); // works
  
var importedfn = myApp.sayHello;

importedfn(); // works

Compare this to the confusing message passing version which uses this.

var myApp = {};

myApp.message = 'hello';

myApp.sayHello = function() {
  alert(this.message);
};

The code using this library is free to write.

myApp.sayHello() // works because "this" refers to myApp object.

var importedfn = myApp.sayHello;

importedfn(); // error because "this" refers to global object.

The lesson to be learned here is that this should never refer to an object being used as a namespace because it leads to confusion about importing identifiers from that namespace. This problem is one of the reasons that this makes my list of JavaScript Warning Words

(This also suggests that a library's API properties should point to the same function so that these functions can be imported into other spaces. This problem was pointed out in the comments of my Lazy Function Definition Pattern article. The lazy function definiton can be used safely when hidden within a library and is not part of the API.)

Nested Object Namespacing

Nested object namespacing is another common practice which extends the idea of object namspacing. You may have seen code like the following

YAHOO.util.Event.addListener(/*...*/)

Resolving the above line requires the interpreter to first find the global YAHOO object and then its util object and then its Event object and then find and call its addListener property. This is way too much work each time an event handler is attached to a DOM element so the concept of importing is used.

(function() {
  var yue = YAHOO.util.Event;
  yue.addListener(/*...*/);
  yue.addListener(/*...*/);
})();

If you know that the YAHOO.util.Event.addListener function does not use the this keyword and always references the same function then the importing could be even more compact.

(function() {
  var yuea = YAHOO.util.Event.addEventListener;
  yuea(/*...*/);
  yuea(/*...*/);
})();

I think nested object namespacing is unnecessarily complex when the goal is simply avoiding identifier collisions. Is Yahoo! not confident that the global identifiers YAHOO_util_Event and YAHOO_util_Event_addEventListener are unique?

I think the motivation for nested object namespacing is to have the appearance of the Java package naming convention which in Java is inexpensive. For example, in Java you may see the following.

package mytools.text;

class TextComponent {
  /* ... */
}

A fully qualified reference to the class above would be mytools.text.TextComponent.

The following package naming description is in Learning Java by Niemeyer and Knudsen.

Package names are constructed hierarchically, using dot-separated naming convention. Package-name components construct a unique path for the compiler and runtime systems to locate files; however, they don't create relationships between packages in any other way. There is really no such think as a "subpackage"; the package namespace is, in actuality, flat—not hierarchical. Packages under a particular part of the package hierarchy are related only by convention. For example, if we create another package called mytools.text.poetry (presumably for text classes specialized in some way to work with poetry), those classes won't be part of the mytools.text package; they won't have the access privileges of package members.

The illusion of nested namespaces in Perl exists also. In Perl, the nested package names are separated by double colons. You may see Perl code like the following.

package Red::Blue;

our $var = 'foo';

A fully qualified reference to the above variable would be $Red::Blue::var.

In Perl, like Java, the idea of a namespace hierarchy is only for the benefit of the programmer, not the language. Programming Perl by Wall, Christiansen and Orwant explains

The double colon can be used to chain together identifiers in a package name: $Red::Blue::var. This means the $var belonging to the Red::Blue package. The Red::Blue package has nothing to do with any Red or Blue packages that might happen to exist. There is, a relationship between Red::Blue and Red or Blue may have meaning to the person writing or using the program, but it means nothing to Perl. (Well, other than the fact that, in the current implementation, the symbol table Red::Blue happens to be stored in the symbol table Red. But the Perl language makes no use of that directly.)

The parenthetical note at the end of the above quotation implies that Perl may have the same identifier resolution cost that using nested namespace objects in JavaScript has. If the Perl implementation changes the cost could disappear. In JavaScript, I believe that the cost of nested object namespacing will never go away because JavaScript uses late-binding.

I don't think nested object namespacing in JavaScript provides any significant benefit but it is potentially very expensive at runtime if importing is not used.

A compromise

If pure prefix namespacing really is slow in some browsers, and the concept of nested namespaces helps keep things organized in the developer's mind then I think the Yahoo! example above could be written as either

YAHOO.util_Event_addListener

or with a few more globals (but still not many for any give page)

YAHOO_util_Event.addListener

Namespacing in which dimension?

Perl CPAN modules are namespaced based on what they do. For example, I wrote a module in the namespace

JavaScript::Minifier

If someone else writes his own module with the same name, and he unknowingly uses the CPAN module by the same name through some module dependency, then a collision occurs.

Java programmers takes the most verbose, but safest, approach, of course. (Java programmers seem to think about code running in huge systems.) In Java, packages are generally namespaced based on both who wrote it and what it does. (A formalization of the myFunc style.) The "who wrote it" part even uses a relatively guaranteed unique name that the developer "owns". If I wrote a Java minifier, it would use the following namespace since I own the michaux.ca domain name.

ca.michaux.javascript.minifier

In JavaScript, after the results of this discussion, this could be written more efficiently as

ca_michaux_javascript_minifier

Because JavaScript is served as text, this sort of namespacing seems too expensive by increasing download time. Gzip compression finds common strings and replaces them with a small string. If gzip is not available then importing could be used.

var ca_michaux_javascript_minifier = {};

(function() {
  var cmjm = ca_michaux_javascript_minifier;
  
  // refer to cmjm inside this module pattern
})();

I'm not suggesting that these long namespaces are necessarily necessary but they are definitely the safest in avoiding namespace collisions.

Other Namespacing Issues

Identifiers are not only created in JavaScript source. The name attribute of a form is added to the document.forms object. It makes sense to namespace these with <form name="myCompany_login">.

Namespacing class name attributes like <div class="myCompany_story"> could be worthwhile also to reduce CSS namespace collisions and when JavaScript code is searching for DOM elements by class name.

Summary

Personally I think that anything like YAHOO.util.Event.addListener, with dots or underscores, is overly paranoid of collisions. It could have been just YUI.on. Dojo provides enough protection with dojo.connect for the same job because it covers the "who" and "what" dimensions of namespacing sufficiently. No one in their right mind is going to come along and write a JavaScript library under the namespace dojo. The Dojo developers will not forget they already have a connect function and write another one.

It might be good if we had a website where programmers could reserve their JavaScript globals identifiers, underscore prefixes and when ECMAScript 4 is released also their package names: "The JavaScript Namespace Registry".

JavaScript is a powerful language with a minimal set of concepts. Even though JavaScript doesn't have language-level support specifically designed for avoiding namespace collisions, there are several ways to solve the problem. There is no one "right" answer. Pick the system you like best.

But please, whatever you do, just don't put another global $ identifier out there!

Extras

comp.lang.javascript discussion on namespacing

Update August 9, 2008 The Linux folks have a namespace registry: LANANA.

Comments

Have something to write? Comment on this article.

kangax June 14, 2008

I ran a little test to see what the actual performance difference is when using global variable vs. a "nested" one. It seems to be somewhat tiny (FF 3rc2, Mac OS X):

var foo={bar:{baz:{qux:{flux: function(){ return 5; } }}}};
var moo=function(){ return 5; };

(function(){
  var s = new Date, result = [];
  for (var i=1e6;i--;) {
    foo.bar.baz.qux.flux();
  }
  result.push((new Date - s) + 'ms');
  s = new Date;
  for (var i=1e6;i--;) {
    moo();
  }
  result.push((new Date - s) + 'ms');
  return result.join(' ');
})();

//returns "1183ms 719ms"
Peter Michaux June 15, 2008

kangax,

I ran the following three tests separately in Firefox 2. I've found that running speed tests in the same execution favors the second test.

I don't call the function in these tests because namespacing is more about resolving the identifiers rather than what happens after they are resolved.

I've added an empty loop test as a control.

var foo={bar:{baz:{qux:{flux: function(){ return 5; } }}}};

(function(){
  var s = new Date();
  for (var i=1e6; i--; ) {
    foo.bar.baz.qux.flux;
  }
  var e = new Date();
  alert(e.getTime()-s.getTime()); // 530 ms
})();

---------

var moo=function(){ return 5; };

(function(){
  var s = new Date();
  for (var i=1e6; i--; ) {
    moo;
  }
  var e = new Date();
  alert(e.getTime()-s.getTime()); // 340 ms
})();

---------

(function(){
  var s = new Date();
  for (var i=1e6; i--; ) {

  }
  var e = new Date();
  alert(e.getTime()-s.getTime()); // 60 ms
})();

Now compare the resolution times of the first two and the difference is quite pronounced.

(530 - 60) / (340 - 60) = 1.68

A million resolutions is many. Some complex event handlers may make this many resolutions but it is not the common case. When discussing something like performance, the common cases are often not the concern but rather the extremes are of interest. This article wasn't intended to say that the nested namespacing is not viable. It is being used on many pages; however, there is no real benefit to using it over a scheme like the compromise I described in the article.

Joseph Pecoraro June 15, 2008

Peter, great article. Namespacing in Javascript is something that I've always been a little hesitant to go into and this showed me some important things. I like the issues you raised with the nested notation, its something I never really considered.

To add to the benchmarks, I ran it on my FF3rc3, Mac OS X 10.5.3 and the difference was actually worse then both of yours. The nested ranging from 1.7 to over 3 times worse. Any idea why the tests could have so much variance?

Peter Michaux June 15, 2008

Joseph,

Sometimes I get a particularly slow run when testing but then again, sometimes I'm typing on my computer and it just freezes for a second or so. Time slicing? Garbage collection? It is hard to say.

Michael June 19, 2008

Hey Peter,

Nice write-up. Can't say that I agree with you completely, but you've made some good points and did end by saying "Pick the system you like best" , fair enough :-)

Javascript Namespacing is one of my passions, strange perhaps, but true. It's been the main motivation behind my creation of Ajile (Advanced JavaScript Importing & Loading Extension).

I currently prefer object based namespacing specifically that using reverse domain names. That said I only believe that level of verbosity is needed when working in an open environment like the web. Here are my top 3 reasons for preferring reversed-domain object-based namespacing:

1. I find object oriented (dot notation) code easier to read and manage. The encapsulation that comes with object-based namespacing allows me to filter functionality both visually at design time and actually at run time. Being able to easily see and request/use what I need has proven to be as important as being able to ignore what I don't.

2. I develop for the web. As you know, it's a large interconnected system (of systems). If ever there was a place where encapsulation and unique identification was needed, it's here. The human readable domain names we use to encapsulate and identify content on the web has proven to be quite effective and so I believe the reverse domain namespacing approach will also be effective in this arena.

3. The web seems to be evolving from disparate sources of content and functionality statically linked, to a dynamic medium where multiple sources interact and exchange information on a regular basis. Being able to confidently and uniquely identify content and functionality is becoming evermore important with the emergence and rapid growth of mashups, widgets, and social networking especially now that they're becoming integrated into our daily lives and the tools we rely on. Reverse domain name object namespacing is a first step towards an assurance of functionality and content ownership. All that's needed after that is enforcement...

I haven't done benchmarking against sites using object-based namespacing, but as you've said importing negates the performance issue, and that's one of the key features I've built into Ajile

Keep the interesting topics coming, more often than not your posts catch my eye, keep it up ;-)

Nathar Leichoz October 29, 2008

I haven't done any tests and I'm just speculating here, but what are the performance differences between:

1) Many functions in the global namespace. e.g., MM_run1(), MM_run2(), MM_run3(), etc. For any and every function call (direct or indirect), the JS engine must sift through all those global functions before it finds the one it needs. Will even calling alert(), slow down the engine because of too many functions in the global scope?

2) All functions hidden behind 1 global object. e.g., dojo.run1(), etc: If calling a normal non-namespaced function (e.g., alert), will it be fast because there is less in the global scope for the JS engine to sift through?

3) Perhaps if all the global functions are stored internally by the JS engine as a hashtable, then the cost of lookup is cheap, but if they are stored as a linked-list, then it would obviously be expensive and hiding all functions behind single global objects would be more efficient?

Peter Michaux October 29, 2008

Nathar,

There have been performance problems of too many global variables in the past. A few things have changed.

The most important change is that using the module pattern, not many things need to be in the global namespace as many functions can be hidden in closures. Even on some very big pages, I only have about 40 global symbols and that isn't many.

Another option is to make a local reference inside a closure to what would otherwise need to be referenced through a global variable. This technique is actually recommended when using objects as namespaces because looking up properties of an object has cost as well.

I don't think anyone would implement a symbol table as a linked list. A hash is the natural way to go.

jQuery Howto January 29, 2009

Great article. Here is an article on how to use it with the jQuery object. In other words namespasing with the jQuery.

Mike Nosal June 12, 2009

Interestingly, accessing the object members with strings suffers a performance penalty in Safari 4.

Looping 1 million times:

foo.bar.baz.qua.flux() foo["bar"]["baz"]["qux"]["flux"]() moo()
Safari 4 229ms 311ms 139ms
Firefox 3.0 yields identical results for both forms 2626ms 2626ms 1906ms

Safari 4 is nearly 10x faster on this test.

Mike Koss January 24, 2011

I just found this post. I use a variant of hierarchical namespaces that does not require a specific load order:

namespace.js

I’ve found it quite useful in building portable modules that I can use between projects.

Have something to write? Comment on this article.