Javascript object literal namespacing

The latest best practices in javascript recommend that object literal notation be used to create a namespace feature of sorts. Object literal notation is ridiculously easy to use and gives a great deal of power to the developer. Here is an example-laden crash course.

Construction

Object literal notation is a feature of javascript that is similar in nature to the hash maps of other languages. Objects are considered to consist of name-value pairs, where the name is a string. If the string is a valid variable name, it can be used as a variable. Here is a sample declaration:

MyStuff = {
	'foo':function(a, b)
	{
		//do stuff
	},

	bar:3,

	quux:
	{
		'3':'b',
		'var':undefined
	}
};

Note that 'foo' could just as well have been declared as foo, with no quotes, because it is a valid variable name.

Usage

Following are some methods of addressing the elements created in that block of code:

MyStuff; // returns MyStuff
MyStuff.foo(1, 2); // executes foo(1, 2)
MyStuff.foo; // returns foo
MyStuff['bar']; // returns bar
MyStuff.quux['var']; // returns undefined
MyStuff.quux['3']; // returns 'b'
MyStuff.quux[3]; // returns 'b' (this demonstrates that arrays are hashmaps as well)
MyStuff.quux[MyStuff.bar]; // returns 'b'

The following will not work:

foo(); // foo must be fully addressed
MyStuff.quux.3; // 3 is not a valid variable name, so it cannot be used directly
MyStuff.quux.var; // var is a reserved keyword, so it cannot be used directly

Namespacing

Complex data may be passed to and returned from functions with a minimum of effort. More importantly, however, developers can build libraries of functions and constants quickly and easily, using a pattern called namespacing. Namespacing allows developers to think less about avoiding collisions in variable and function names and focus more on the code's functionality. Yahoo uses this pattern to great effect.

Watch out for overwriting, though. If I have already loaded the MyStuff object as defined above and I want to extend one of the sub-objects, the following will not work:

MyStuff = {
	quux:
	{
		newObj:
		{
			a:1,
			b:2
		}
	}
}

That block of code will destroy MyStuff's 'foo' and 'bar' fields and MyStuff.quux's '3' and 'var' fields. Here is the proper technique for adding code to an existing object:

MyStuff.quux.newObj = 
{
	a:1,
	b:2
}

Notes

Each name-value pair is separated from its neighbors by a comma, and internally delimited by a colon. The last pair must not be followed by a comma! Firefox will not care, but Internet Explorer (and Safari) certainly will, announcing a "missing string terminal" or some such error.

Jonathan Snook notes that just as quux['3'] and quux[3] have the same meaning, quux = {3:'b', '3':'c'}; will result in quux[3] == 'c'. Seems that numeric keys are converted to strings behind the scenes.


Responses: 15 so far

  1. Shawn Anthony says:

    Tim, I have no idea how I missed it, but I didn't realize you knew javascript so well! Cool. I'm off to look for any tuts on your blog. Do you know where I can learn about making a script that rotates a few website URLs?

  2. Tim McCormack says:

    I'm pretty sure this is the first guide or tutorial that I've written. I'm completely self-taught in CSS, HTML, and JavaScript, lacking any formal training, so don't take what I write as expert advice. That being said, I immensely enjoy playing in these languages, so I do have an excellent working understanding of them.

    What do you mean by "rotates a few website URLs"? If I understand you correctly, you want to display several of a set of URLs on any given page view, randomly chosen. That would be a server-side task best handled with PHP, not a client-side task best handled with JavaScript.

  3. Shawn Anthony says:

    Tim, self-taught seems to be the way to go. What little I know has been aquired that way too. Good for you.

    When I was a member of "a certain-not-to-be-named Network," we were provided with a bit of javascript which would show a random number of site pulled from the entire network. The script I added to my template looked like this:

    adText = new Array;
    adText[0] = "<li><a href=\"http://chefvault.com\" title=\"Chef Vault\">Chef Vault</a> by The Chefs </li>\n";
    adText[0] += "<li><a href=\"http://ikiw.org/\" title=\"Using Wiki in Education\">Using Wiki in Education</a> by Stewart Mader </li>\n";
    
    //snip
    
    adtext[0] += "<li><a href=\"http://binarybonsai.com/\" title=\"Binary Bonsai\">Binary Bonsai</a> by Michael Heilemann </li>\n";
    adtext[0] += "<li><a href=\"http://bradgarland.net\" title=\"Brad Garland\">Brad Garland</a> by Brad Garland </li>\n";
    document.write('<ul class="9roll">'+adText[0]+'</ul>');

    Any ideas?

  4. Tim says:

    Tim,

    An excellent look at a powerful concept. Im building a lib based on prototype now and your reminder that arrays can serve as hashmaps gave me an idea for this implementation. Thanks, Ill share the code when I finish it. Good Work!

  5. Tim McCormack says:

    Prototype is a gorgeous library. I also recommend Behaviour, which allows you to apply javascript to elements using CSS selectors.

  6. Gianni Milanesi’s Weblog » Blog Archive » JavaScript-Fu: Guidelines for Web 2.0 Mastery says:

    [...] Namespacing in its essence is the art of clearly seeing your code as one being. Namespacing is the path to prevent clashing of variable and function names in the jungle of scripts, and is one of the points of the JavaScript-Fu Star of Unobtrusiveness.The way of the Namespace is simple and clear once you learn to understand its true meaning. The following mantra can help you better understand the path you have to follow to reach the Namespace nirvana through the use of Object Literal Namespacing: [...]

  7. Tim McCormack says:

    Gianni has written an excellent guide to clean, modern JS authorship -- check it out.

  8. eduardo lundgren says:

    how can i´ll create objects, using namespaces , like this..

    obj1 = new MyStuff(myParam);
    obj2 = new MyStuff(myParam2);

    because my application will can called undefined times... and i dont seeing how it can be possible with namespaces...

  9. Tim McCormack says:

    Hmm, I haven't considered how to use namespaces to organize classes -- I've ony used it to organize functions and constants.

  10. DerekAllard.com » Blog Archive » Javascript object literal namespacing says:

    [...] Tim McCormack has an excellent summary of Javascript object literal namespacing. [...]

  11. DaCoder says:

    Eduardo,
    Ajile might be what you're looking for. Take a look at http://ajile.iskitz.com/

    Look at the Examples section and the API & FAQs section for details.

  12. paul says:

    in regard to eduardo lundgren's problem. here is my solution to making instances of objects/classes

    var RequestsList = function(){
    	var RequestsL = {
    		changed: false,
    		list:[],
    		add: function(player){
    			RequestsL.list.push(player);
    			changed = true;
    		},
    		print: function(){
    			output(RequestsL.list);
    		}
    	};
    	return RequestsL;
    };
    
    
    var requests = new RequestsList();
    var requests2 = new RequestsList();

    i hope that this helps people who want to use object literal notation.

  13. JavaScript Object Literal Namespacing « Crying Glowing Sun says:

    [...] Tim McCormack on Javascript object literal namespacing [...]

  14. M A Hossain Tonu says:

    Just updated my post using your post.(didn't found trackbackURI :( ) My post on the same topic is here:

    "JavaScript Object Literal Namespacing"
    http://mahtonu.wordpress.com/2010/04/13/javascript-object-literal-namespacing/

  15. Simple Slider show using Javascript - JS Slide show script says:

    [...] One simple fix is to wrap it in an anonymous, self-invoking function. Another is to use JS's namespace pattern ([2]): make the variables and functions properties of an object literal. The first essentially [...]