Play Nice With Others: JavaScript Namespace

Good Job!

Ever had a friend with the same first name? I did. Growing up, through elementary school, I had a good friend named Jeff Shaddock. This posed a problem for most of our teachers as the typical “first name, last initial” solution for children with the same name didn’t work. On assignments and tests, I was usually forced to be Jeff Sa. and likewise, my friend Jeff was forced to be Jeff Sh. so people knew which one of use was which.

Similar situations often crop up when dealing with web applications and JavaScript. Since JavaScript doesn’t complain when you declare a function multiple times and it simply uses the last declared version, if you have a few different libraries, each doing their thing, you need to make sure they don’t conflict. If you’re planning on writing a new library, or improving an existing one, you can avoid frustration by keeping two simple things in mind: be unique and don’t share. ###Be Unique: Pick a name Pick a good name and make sure it’s unique. If you’re writing an event object, don’t call it event. Pick a unique prefix for all your objects so you can easily distinguish your objects from the rest. Maybe use your initials or your company name, however in my case JSEvent probably wouldn’t be much better since JS could mean JavaScript too. If you simply use event and someone else creates event with a different API, you’re going to have problems.

Don’t Share: Protect your helpers

When writing your libraries, you may often find a need for internal, specialized functions that aren’t necessarily part of the overall library API, but they would make it much easier to write or maintain. Let’s say you want to create a library and one of the functions you want to make accessible to everyone is JeffreyInnerHTML(), which simply alerts the innerHTML property of an HTML Element. To make your life easier, you might create a function called $ to grab elements by id and use it with other functions in your library:

function $(id) {
	return document.getElementById(id);
}

function JeffreyInnerHTML(id) {
	alert($(id).innerHTML);
}

That’s great, but your $ function isn’t the same as the common Prototype function, so now some other public libraries, that are expecting different functionality, will stop working. To keep your $ function to yourself, you can employ some JavaScript trickery:

(function(){

	function $(id) {
		return document.getElementById(id);
	}

	function InnerHTML(id) {
		alert($(id).innerHTML);
	}
	
	window['JeffreyInnerHTML'] = InnerHTML;

})();

With this trick, all your functions are encapsulated and protected in an anonymous function (function(){ /* code */ }). By encapsulating everything in an anonymous function, all your functions, objects and variables will have access to each other, but no other parts of the script are able to use your functions. You’ll notice I’ve renamed JeffreyInnerHTML() to InnerHTML() to illustrate the point. Outside of the encapsulation there’s no way to execute InnerHTML(). Your $ function is now your own, along with anything else inside the encapsulation. But then how do you allow other scripts to access a function called JeffreyInnerHTML()?

To globalize part of your protected API, the trailing () tells JavaScript to execute the anonymous function right away. The magic happens in the execution of the last line where the InnerHTML function is assigned to a window member window['JeffreyInnerHTML'].

{.caution}Remember not to include the () on the function when assigning. If you do, InnerHTML() will execute and the result of the function will be assigned, not the function itself.

In a web browser, the JavaScript window object is the global ‘root’ object that contains everything. By assigning your InnerHTML function to window['JeffreyInnerHTML'] you’re effectively creating a general function, with a nice namespace, called JeffreyInnerHTML that executes as if it were the protected InnerHTML. The tricky part however is when you call JeffreyInnerHTML(), it will execute in the space of your anonymous function so it will still have access to your special $ function and anything else you have in there, along with anything outside of the encapsulation.

The other advantage of the anonymous function encapsulation is that you don’t need to append your namespace prefix to dozens of functions and objects. The only part where you need to worry about namespace and inadvertently overriding something, is in the assignment to the window object. Of course, within your anonymous function, any function you override, like $, will act differently but you’ll be aware of the change and it won’t be a problem.

That’s all on namespaces for now. Since elementary school, Jeff Sh. and I have lost touch. Maybe I’ll look him up sometime and see what he’s up to.