Using Objects to Organize Your Code

categories: howto, jquery

This is a reprint of an article that originally appeared in the March 2009 issue of JSMag.

When you move beyond simple snippets of jQuery and start developing more complex user interactions, your code can quickly become unwieldy and difficult to debug. This article shows you how to start thinking about these interactions in terms of the bits of behavior the feature comprises, using the object literal pattern.

In the past few years, JavaScript libraries have given beginning developers the ability to add elaborate interactions to their sites. Some, like jQuery, have a syntax so simple that people with zero programming experience can quickly add bells and whistles to their pages.

Adding all those bells and whistles, even some pretty elaborate ones, seems to be just a few Google searches away. A copy here, a paste there, a plugin or a few dozen lines of custom code — the client is duly impressed, and you’re adding jQuery to your resume.

But wait. Now the requirements have changed. Now the thing that needed to work for three elements needs to work for ten. Now your code needs to be reused for a slightly different application where all the IDs are different.

We’ve all seen the snippets that make jQuery (and other libraries) look dead-simple. What those snippets leave out — and hey, they’re just snippets, right? — is how to design your code when your needs go beyond dropping in a plugin or doing some show() and hide().

Introducing the Object Literal pattern

The object literal pattern offers a way to organize code by the behaviors it comprises. It’s also a means to keep your code from “polluting the global namespace,” which is a good practice for all projects and imperative for larger ones. It forces you to think at the outset about what your code will do and what pieces need to be in place in order for you to do it.
An object literal is a way to encapsulate related behaviors, as shown here:

var myObjectLiteral = {
	myBehavior1 : function() {
		/* do something */
	},
 
	myBehavior2 : function() {
		/* do something else */
	}
};

As an artificially simplistic example, suppose you had the jQuery shown in Listing 2 for showing and hiding content when a list item was clicked.

$(document).ready(function() {
	$('#myFeature li').
		append('
<div>').
		each(function() {
			$(this).find('div').
				load('foo.php?item=' + $(this).attr('id'));
		}).
	click(function() {
		$(this).find('div').show();
		$(this).siblings().find('div').hide();
	});
});</div>
 

Simple enough, and yet even in this example there are several things you might want to change later — for example, the way you determine the URL for loading the content, the destination of the loaded content, or the show and hide behavior.

An object literal representation of the feature cleanly separates these aspects. It might look like this:

var myFeature = {
	config : {
		$wrapper : $('#myFeature'),
		container : 'div',
		urlBase : 'foo.php?item='
	},
 
	init : function(config) {
		$.extend(myFeature.config, config);
		myFeature.config.$wrapper.find('li').
			each(function() {
				myFeature.getContent($(this));
			}).
			click(function() {
				myFeature.showContent($(this));
			});
	},
 
	buildUrl : function($li) {
		return myFeature.config.urlBase + $li.attr('id');
	}, 
 
	getContent : function($li) {
		$li.append(myFeature.config.container);
		var url = myFeature.buildUrl($li);
		$li.find(myFeature.config.container).load(url);
	},
 
	showContent : function($li) {
		$li.find('div').show();
		myFeature.hideContent($li.siblings());
	},
 
	hideContent : function($elements) {
		$elements.find('div').hide();
	}
};
 
$(document).ready(function() { myFeature.init(); });

Because the initial example was incredibly simplistic, the object literal incarnation is longer. Truth be told, the object literal method generally won’t save you lines of code. What it will save is headaches. By using an object literal, we’ve broken our code into its logical parts, making it easy to locate the things we might want to change down the road. We’ve made our feature extendable, by providing the ability to pass in overrides to the default configuration. And, we’ve done some limited self-documentation — it’s easy to see at a glance what the feature does. As your needs grow beyond the simplicity of this example the benefits of the structure will become clearer, as you’ll see below.

Note: For an excellent primer on objects, properties, and methods, check out Object-Oriented JavaScript: Create scalable, reusable high-quality JavaScript applications and libraries by Stoyan Stefanov. You may also want to read up on JSON (JavaScript Object Notation).

An in-depth example

Our mission will be to create a UI element that features multiple pieces of content divided into several sections. Clicking on a section will show a list of items in the section; clicking on an item in the left nav will show the item in the content area. Whenever a section is shown, the first item in the section should be shown. The first section should be shown when the page loads.

Step 1: Crafting the HTML

Writing good semantic HTML is a crucial prerequisite to writing good JavaScript, so let’s start by thinking about what the HTML for something like this might look like. The HTML should:

With those guidelines in mind, we’ll start with this html.

Note that we haven’t included any markup to display the section navigation or the item navigation; those pieces will be added by jQuery since they will only work with jQuery; non-JavaScript users will get nice semantic markup. (If there’s anything surprising or confusing in that HTML, now would be a good time to read up on POSH (plain-old semantic HTML) and progressive enhancement.)

Step 2: Scaffolding the Object

My first step in creating an object for a feature is to create “stubs” within the object. Stubs are basically placeholders; they’re the outline for the feature we’re going to build. Our object will have the following methods:

4 Responses to “Using Objects to Organize Your Code”

  1. Viet says:
    October 26th, 2009 at 3:12 pm

    Hi There,

    I’m new to jQuery, and this was a great and insightful article. However, I believe there’s a typo, this line:

    var url = myFeature.getItemURL($item);

    should be (missing config?):

    var url = myFeature.config.getItemURL($item);

    Thanks!

  2. Rebecca says:
    October 26th, 2009 at 3:17 pm

    Viet: Thanks for catching that, it’s fixed now :)

  3. Matt says:
    November 6th, 2009 at 1:40 pm

    Thanks! There seems to be a significant need for tips like this. Well done.

  4. edouard says:
    November 12th, 2009 at 3:15 am

    Hi there,

    thx a lot for all this, it’s exactly what I was looking for …
    I need the browser buttons so I’ll post something if I can handle it with jQuery history, thx again for sharing,

    @doud

Comment