JavaScript Namespaces

The idea of creating JavaScript namespaces are coming up more and more. With the expanded use of OPC (Other People's Code &mdash "you down with OPC?"), the idea of using or taking advantage of JavaScript namespaces is coming up more and more.

What is a JavaScript namespace?

More importantly, "what is a namespace?" A namespace is a container and allows you to bundle up all your functionality using a unique name. In JavaScript, a namespace is really just an object that you've attached all further methods, properties and objects. Take a look at the JavaScript source for this site and you'll see that I've attached all my functions to a snook object. Dustin Diaz bundles up all his stuff under DED.

Are namespaces in JavaScript necessary?

Yes and no. Semantically speaking, are they necessary, of course not. You can have every function be in the global (aka window) namespace. This is the way it has generally been done since JavaScript was introduced over 10 years ago.

But should namespaces be the way to go? Creating a namespace for your code helps prevent the overwriting of existing function names (which, the larger your application is, the more likely it is to happen). It's also a step in the object-oriented direction, which promotes modularity and code re-use. On the other hand, it can make your code more verbose than it needs to be. Which would you rather use[1], $() or YAHOO.util.Dom.get()?

Setting the standard?

At this point, there really is no standard way but as more and more people start thinking of this, maybe it's time to come up with a simple and consistent approach. This is a call out to all my JavaScript brethren: do you support the idea and if so, how would you implement it?

Should the namespace be based on the domain name like it is in Java? My namespace would be ca_snook or snook_ca. Should it be uppercase, like YAHOO or DED or SNOOK?

[1] You could do var $ = YAHOO.util.Dom.get; to keep things simple.

Published June 18, 2006 · Updated September 14, 2006
Categorized as JavaScript
Short URL: https://snook.ca/s/616

Conversation

23 Comments · RSS feed
Miles Johnson said on June 19, 2006

I use namespace whenever I do javascript. It all depends on what im using it for, if im doing it for a client I usually use there company name or domain name for the name space. Where as if its for myself, I use initials. Namespaces are a great thing to use on your own site, but if your giving a free script away, many might find it confusing.

Andrew Dupont said on June 19, 2006

Should the namespace be based on the domain name like it is in Java? My namespace would be ca_snook or snook_ca. Should it be uppercase, like YAHOO or DED or SNOOK?

I don't know if it's really necessary to agree on some sort of convention for this. I think that no matter how elaborate the convention will be, naming collisions will be a theoretical possibility. Namespaces just reduce the likelihood of such collisions by at least an order of magnitude.

JS2, however, will handle "packages" exactly this way � with Java's reverse domain notation. That way you can just do "import net.conio.prototype.2_0" and have total control over what goes into your "window" namespace.

You could do var $ = YAHOO.util.Dom.get; to keep things simple.

Yeah, and this is JS1's poor-man's "import." In Prototype, for instance, you could define "snook.widgets.fixedCommentForm" as an object, so that others can use your code more safely, but Object.extend it onto "window" just for your own convenience in the scriptwriting process.

Mark Wubben said on June 19, 2006

What about using the name of the script as it's namespace (for small scripts, of course). You can also prefix global variables, or if your code is in a controlled environment don't namespace at all.

Bramus! said on June 19, 2006

Namespaces are good indeed. Above that some guidelines should be set out. Here's some of my thoughts/ideas (which I already implement in the projects I've done):
- The root namespace cannot hold any functions itself. --> Group everything into packages, like _root.formchecker
- Provide a main and misc package.
- The _root.main should hold an init(), from there you should trigger other init() functions (_root.formchecker.init(), _root.datepicker.init(), etc.) based on the criteria you set ('if the document has forms and the classname of the form is checkme, then hook the formchecker to the form'). Then the author only has to add the _root.main.init() to the load event of the document.
- ...

Just a small kickoff here...

Bramus!

Jonathan Snook said on June 19, 2006

Mark, are you being facetious?

Teevio said on June 19, 2006

Great topic here...

I would steer toward all caps. Generally speaking, ca_snook or caSnook would be referring to a variable in code land. For objects it is typically done CaSnook and Globals are CASNOOK. Since the namespace is as Global as it gets in Javascript I think the all caps way should be used.

With this you would see hierarchy, SNOOK.Object.variable, from greatest to least. and someone not familiar with the code could understand from a glance at least part of the structure being used in the code.

Lowell said on June 19, 2006

Yeah you know me!

Mark Wubben said on June 19, 2006

Jonathan, I wasn$this->normalizeEntities16bit("8217")t intending to come across like that. My point is that I don$this->normalizeEntities16bit("8217")t really believe in extensive namespaces, as long as my the code is uniquely distinguishable from the code of others.

As an example, would sIFR have warranted the use of net.novemberborn.sIFR, or is sIFR good enough?

Hermann Klinke said on June 19, 2006

I don't think we should capitlize namespaces. In most conventions capitalization means that the variable is a constant. I like the .NET/Microsoft convention, because it's simple and consistent: Company.Product or Company.Product.Component

Jonathan Snook said on June 19, 2006

Mark: for the record, I'm not a big fan of the overly lengthy approach that Yahoo has taken nor do I think a Java style approach is the best. I just wanted to see what others were thinking on the matter. sIFR or SIFR (if we went all uppercase as a convention) is just fine.

I suppose secondary to namespacing is how do we program in such a way as to make it easier to change an application's namespace if need be?

Joe said on June 19, 2006

I agree with Teevio, names starting with lowercase would seem to imply a variable whereas uppercase would imply objects or globals.

Jeff L said on June 19, 2006

Is this much different than using the Object Literal notiation that Chris and Dustin both wrote about some time back?

Mark Wubben said on June 19, 2006

Changing a namespace would be quite hard, unless you go the XML way where the namespace is actually the URI, not the name you use in the markup. That'll require new JavaScript syntax, though.

Jonathan Snook said on June 19, 2006

Jeff: Yes, this is different. The Object Literal is a programming construct in JavaScript. This discussion is more about establishing a naming convention.

Dustin Diaz said on June 19, 2006

I'm not sure what makes $ = YAHOO.util.Dom.get; a poor mans import. It's quick and practical and does exactly what you want it to do within your own defined local scope.

Also, I too agree that they're good and and, well, not bad, but they can be unnecessary in some cases. When developing at Yahoo! (the worlds largest website), there is a need for the verbosity - which actually isn't so much, but seems to be getting a lot of flack for it's 4th tier of spaces to do a real function.

With my own stuff that I develop and maintain, I find that it's no big fuss to just leave them under 2 or 3. Eg:

DED.get
or
DED.util.addEvent

Anyway, on the topic of all caps, there was a post on the YUIBlog just a while ago about why we chose all caps for the first-tier namespace. Reason being that first of all, we wanted to keep things a bit practical, so no Com_Yahoo or Yahoo_Com stuff. Second, we didn't want someone to think it was just a plain 'ol function, so all lowercase was out of the question, plus capitalizing the first letter would confuse it as a constructor.

Realistically speaking, it is very, very unlikely that someone is going to accidently override the YAHOO object. I really see nothing wrong with using all caps as your global object namespace.

Does all this need to be a standard? Well, I don't know. It hasn't been too much of an issue thus far. Indeed Yahoo! has been the first to cause people to complain about them (go figure) so far, but really, as long as I know what the namespace is and you have a little comment in your code about it, I'm cool with that.

Ya see, I'm fine with this:


/*===========
		SNOOK NAMESPACE
		you gotta keep em separated.
*/
Andrew Dupont said on June 19, 2006

I'm not sure what makes $ = YAHOO.util.Dom.get; a poor mans import. It's quick and practical and does exactly what you want it to do within your own defined local scope.

Dustin, I didn't mean that in a bad way. I meant that it's a good way of importing frequently-used functions into the window namespace. It's not as elegant as an import statement, but JS1 doesn't have those, so that's why it's a "poor-man's" import.

Regardless of the strategy or naming convention you use, I think that simple mindfulness of namespace issues is enough. Prototype's $ function was so named, I would imagine, because few people were likely to realize that the dollar sign is a valid character for identifiers in ECMAScript. So the likelihood that $ would overwrite some other method is (or at least was) almost nil. (Prototype also attaches methods to existing objects — Element, Event, etc. — wherever possible in order to lessen its footprint.)

I think that if you write code that is meant to be used by others, you must address naming collisions one way or another, and the simplest way to do that is to stick everything behind a namespace that is unlikely to be shared by something else. But, as Dustin points out, the definition of "unlikely" depends on the scope in which your code is used.

Yahoo runs some of the largest web sites on the planet, so they have to be extra-careful about namespaces. If I'm just writing some JS for my blog, however, I can be a bit more lax. I won't be so lax as to name things init() or run(), but I won't stack things four levels deep the way YUI does.

Mark Wubben said on June 19, 2006

Yahoo runs some of the largest web sites on the planet, so they have to be extra-careful about namespaces. If I$this->normalizeEntities16bit("8217")m just writing some JS for my blog, however, I can be a bit more lax.

Yahoo is writing for its own websites, so namespacing shouldn$this->normalizeEntities16bit("8217")t be as much of a problem as long as the different departments can agree on the functions. If not, a namespace is a safe bet. As Yahoo also makes its libraries publicly available, a namespace becomes necessary.

micha said on July 07, 2006

Another tack you could take is using some sort of JS compiler, like the way the Google Web Toolkit does it. Then you have the benefit of a small footprint with all the namespaces and modularity of regular java in your source code. Does this make any sense?

Michael Lee said on July 17, 2006

It's interesting to see all so much talk about JavaScript Namespaces. Looks like more people are seeing the need.

I've written Ajile to make creating and working with JavaScript Namespaces pretty simple. It's a JavaScript module that provides namespace, import, and load directives/functions for working with namespaces. It even provides a way to use aliases when importing.

Check it out at ajile.iskitz.com.

Brad Fults said on December 27, 2006

Using all caps is ugly.

I'm in favor of pretty code, so "sIFR" and "Yahoo" would take precedence.

I can't decide whether it's funny or tragic that "Ajile" pollutes the global namespace with its namespacing helper "directives" and functions.

Kaanon said on March 13, 2007

I personally can't stand the YAHOO.util.... way. When I first tried out YUI, the first thing i did was immediately "alias" $ (admittedly because I was used to Prototype)

I also like the idea of namespaces to identify where code is. myJS is obviously functions that i'm comfortable with someone in my team working on, while theirJS are functions we want to leave alone (like an external library)

Rian Orie said on April 26, 2007

Now, first off.. I'm not that big of a javascripter at all.. so if I'm out of place here, just kick me in the head ;)

My roots are in the PHP coding, nice clean OO PHP.. why not stick to that?

Instead of var X = YAHOO.util.Dom.get(); do.. var X = new YAHOO; making it X.util.Dom.get() and totally clearing the whole namespace argument.. but I suppose one could then argument the name of objects.. hm.

Michael Lee said on September 07, 2007

@Brad - I'm not sure what you mean by pollution... could you explain? A quick peek at the DOM with Firebug doesn't show "pollution". Maybe you misunderstand Ajile's intent.

Ajile's directives are intentionally published as top-level functions and named as they are in an effort to stay as close to the planned JavaScript directives (import, namespace, etc.) as possible. They are cross-browser substitutes for JavaScript's native import and namespace directives (currently unavailable in most browsers).

You might say: Why not follow the Yahoo approach and nest those directives within the Ajile base object? . . . My answer: Why force users/developers to learn/type more than necessary to perform what's more or less a trivial task in traditional OO languages. In my opinion:

Import ("ca.snook.*")

is shorter and clearer in intent than:

Ajile.import ("ca.snook.*")

Developers familiar with import statements will instantly recognize its purpose and are less likely to wonder "what will that do?"...

If you'd like to have a real conversation about Ajile instead of just posting snide remarks let's do that.

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.