Show love to the object literal

Thursday, February 16th, 2006 at 9:23 pm

German Visitors: Zur deutschen Version gehts hier – auf dem Blog von Jens Grochtdreis

If you are just getting your teeth into JavaScript, or if you used it in the past and re-discovered it in the wake of the AJAX craze you might have been baffled by scripts that come in a new syntax.

While older copy and paste scripts looked like this:

var commonSense=null;
var standardsCompliance="50%";
function init(){
  // code
}
function doStuff(){
  // code
}
function doMoreStuff(){
  // code
}

Newer scripts inside tutorials tend to look like this:

awesome={
  commonSense:null,
  standardsCompliance:"50%",
  init:function(){
    // code
  },
  doStuff:function(){
    // code
  },
  doMoreStuff:function(){
    // code
  }
}

The new syntax is called the object literal and is pretty close to sliced bread. Here is why:

The problem with global functions and variables.

One of the biggest obstacles of JavaScripts you find in the wild is that they tend to claim the browser and variable names for themselves exclusively. If you only apply one script to your HTML document, that is not an issue, but when you use several scripts you might get into trouble.

If you check some of my older articles you will realise that I tended to use rather generic function names like init()  or  validate() . You might also have encountered scripts by me or other people that use global variables like  selectedItem or  current .

Global variables are those that are defined outside functions or inside functions without using the var keyword.

Imagine several developers had the same grand idea and you apply both scripts to your web page:

<script type="text/javascript" src="easyFameAndFortune.js"></script>
<script type="text/javascript" src="thirdPartyStuff.js"></script>

My code in easyFameAndFortune.js will not be executed at all, as the functions init() and validate() have been redefined � or you could say overwritten � by the functions with the same name in thirdPartyStuff.js. If both scripts shared a global variable named current functions in both would overwrite the value needed for the other.

It is the same phenomenon you might have encountered with several style sheets applied to the same document. You change, hack and debug in the main style sheet and wonder why nothing works until you realise that the bug is actually in a different style sheet where you or someone else applied something to the same selector you try to debug.

How to avoid the problem?

There are several solutions:

  • Don’t use generic names in your scripts (which is a shame as init and validate does what it says on the tin)
  • Add a name to each of the functions like easyFameAndFortune_init and easyFameAndFortune_validate
  • Turn the functions into methods and the variables into parameters of an object

The latter is what higher programming languages like Java, PHP or C# do, although that instead of an object, they use classes. There are no classes in JavaScript, so we will have to do with an object.

myscript=new Object();
myscript.current=1;
myscript.init=function(){
  // some code
}
myscript.validate=function(){
  // some code
}

This means that unless both scripts have the same object name (you might want to avoid calling the object init) they won’t overwrite each other. This makes the script play nicely with other scripts, but it still feels a bit cumbersome to repeat the object name every time you add a new method or variable. The solution for that is the object literal, a JavaScript syntax that has been around for quite a while but wasn�t used much in publicly available scripts. It does the same as the earlier script, but the syntax changes slightly:

myscript={
  current:1,
  init:function(){
    // code
  },
  validate:function(){
    // code 
 }
}

Instead of = signs you use : to define the parameters and methods, and instead of semicolons, you need to end each definition but the last one with a comma.
Notice, that the curly brace ending the method validate has no comma. If you were to add another method, it would need one:

myscript={
  current:1,
  init:function(){
    // code
  },
  validate:function(){
    // code 
 
  },
 
  send:function(){
    // code 
  }
}

Spread the message

Not only does the object literal ensure that your script is self contained and you don’t have to repeat the object name � it also sends a message that your script is modern and tries to stay as unobtrusive as possible.

Consider it a secret handshake between DOM scripters :-)

Share on Twitter