Namespacing in JavaScriptAngus Croll | January 11, 2011 Global variables should be reserved for objects that have system-wide relevance and they should be named to avoid ambiguity and minimize the risk of naming collisions. In practice this means you should avoid creating global objects unless they are absolutely necessary. But, hey, you already knew all that….. So what do you do about it? Conventional wisdom tells us that the best global abatement strategy is to create a small number of global objects which will serve as de facto namespaces for underlying modules and subsystems. I’m going to explore several approaches to namespacing, culminating in an elegant, safe and flexible solution that I based on a recent article by James Edwards. Static NamespacingI’m using static namespacing as an umbrella term for solutions in which the namespace label is effectively hard coded. It’s true, you could re-assign one namespace to another but the new namespace will reference the same objects as the old one. 1. By Direct AssignmentThe most basic approach. Its verbose and if you ever wanted to rename the namespace you’ve got a job on your hands. However it’s safe and unambiguous. You could make future maintenance a little easier by using 2. Using Object Literal NotationNow we need only refer to the namespace name once, so switching the name later is a little easier (assuming you haven’t already referenced the namespace too often). There is still a danger that the value of 3. The Module PatternI find myself using the module pattern more often these days. The logic is shielded from the global scope by a function wrapper (usually self-invoking) which returns an object representing the module’s public interface. By immediately invoking the function and assigning the result to a namespace variable, we lock up the module’s API in the namespace. Additionally any variables not included in the return value will remain forever private, visible only to the public functions that reference them. Like the object literal example above, the receiving namespace can be easily switched, but there are added advantages: object literal notation is rigid – it's all about property assignments, with no room for supporting logic. Moreover all properties must be initialized and property values cannot easily cross reference one another (so, for example, internal closures are not possible). The module pattern suffers none of these constraints and gives us the added benefit of privacy. Dynamic NamespacingWe could also call this section namespace injection. The namespace is represented by a proxy which is directly referenced inside the function wrapper – which means we no longer have to bundle up a return value to assign to the namespace. This makes namespace definition more flexible and makes it very easy to have multiple independent instances of a module existing in separate namespaces (or even in the global context). Dynamic namespacing supports all the features of the module pattern with the added advantage of being intuitive and readable. 4. Supply a Namespace ArgumentHere we simply pass the namespace as an argument to a self-invoking function. The We can even set the context to the global object (with a one word change!). This is a big asset for library vendors – who can wrap their features in a self-invoking function and leave it to the user to decide whether they should be global or not (John Resig was an early adopter of this concept when he wrote JQuery). 5. Use this as a Namespace ProxyA recent posting by James Edwards piqued my interest. My Favorite JavaScript Design Pattern was apparently misunderstood by many commentators, who thought he might as well resort to the module pattern. The article peddles multiple techniques (which probably contributed to readers’ confusion) but at its heart is a little bit of genius which I’ve revamped and presented a namespacing tool. The beauty of the pattern is that it simply uses the language as designed – nothing more, nothing less, no tricks, no sugar. Moreover because the namespace is injected via the this keyword (which is static within a given execution context) it cannot be accidentally modified. Even better, the Of course if we wanted a global id generator, it’s a breeze… The id generator tool we’ve been using as an example does not do justice to the full potential of this pattern. By wrapping an entire library and using the this keyword as a stand in for the namespace we make it easy for the user to run the library in whichever context they choose (including the global context). Other considerationsI try to avoid nested namespaces. They are harder to follow (for both human and computer) and they will bulk out your code with cruft. As Peter Michaux points out, deeply nested namespaces may be a legacy of nostalgic Java developers trying to recreate the lengthy package chains they knew and loved. It’s possible to span a single namespace across .js files (though only by namespace injection or direct assignment of every variable) however you should be careful with dependencies. Moreover binding a namespace to a file can help the reader more easily navigate the codeline. Since JavaScript has no formal namespace construct, there is a rich landscape of home grown solutions out there. This survey details just a few of them and there may well be better techniques that I did not cover. I’d love to hear about them. Copyright 2010, Angus Croll - published with permission |