Show love to the object literal
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 .
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
initandvalidatedoes what it says on the tin) - Add a name to each of the functions like
easyFameAndFortune_initandeasyFameAndFortune_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 :-)
February 17th, 2006 at 3:21 am
I've bookmarked this on delicious, as I feel there is some good info here that someday I'll be able to understand. :-)
February 17th, 2006 at 11:04 am
Good post Christian, thanks! Just yesterday when I was browsing some ajax/ dom /javascript scripts and libraries the question on my mind was: ok, all very nice, but what happens if I combine some of these functions and libraries? This article is bookmarked :)
February 17th, 2006 at 12:19 pm
a question about parameters in the object literal notation. can you only have literals as parameters or you also have parameter values be functions like so:
name = {
parameter1 : document.getElementById('id');
function1 : function() {
code...
}
}
February 17th, 2006 at 12:38 pm
No, for the reason that they are not available when the document hasn’t loaded yet.
If you tried to use a:
Outside a function called onload of the window it will also result in an error.
If you want to assign new parameters of the main object, you can do that in a method:
Will work, and you’ll have the DIV as myStuff.myVariable. However, it is always a good idea to test if the DIV with the ID really exists before assigning it to a parameter.
You can also keep the ID as a parameter, which is the option I normally choose to keep it out of the methods:
February 17th, 2006 at 1:42 pm
Don’t forget the arry literal!
var arr = [];instead ofvar arr = new Array();February 17th, 2006 at 3:27 pm
I hate to rain on the parade. I do love Object literals, and Array literals and all the other lovely things that don't work in IE 5.
Unfourtunately my boss likes things to work in IE 5 because people complain if they don't. So I tend to have to use the x = new Object; x.a = blah; and so on method.
Of course you can always go with the IE 5 gets nada method (which I've been pushing for for a while)
February 17th, 2006 at 5:10 pm
¿Are you sure? Because I tested some scripts with Object literals on IE4, and they work beautifully.
var obj={
pr0n:'jdksnjk',
n0rp:'jsadier'
}
alert(obj.pr0n);
It displays what it should!
February 18th, 2006 at 9:10 pm
"I hate to rain on the parade. I do love Object literals, and Array literals and all the other lovely things that don’t work in IE 5."
vs
"Are you sure? Because I tested some scripts with Object literals on IE4, and they work beautifully."
Presumably this'd be IE5 for the Mac - aptly described as a "buggy piece of crap" on Quirksmode.
February 19th, 2006 at 12:57 pm
February 19th, 2006 at 3:52 pm
Thanks for that Chris. I consider
var awsome={ ... };a slightly better coding style.February 19th, 2006 at 5:15 pm
I personally hate object literal notation. The following feels more natural and it’s possible to add classes, objects and members to existing objects and namespaces:
instance:
var awesome = new Object();
awesome.commonSense=null;
awesome.standardsCompliance="50%";
awesome.init = function (){
// code
}
awesome.doStuff = function(){
// code
}
awesome.doMoreStuff = function(){
// code
}
class definition
function awesome()
{
//constructor
}
awesome.prototype.commonSense=null;
awesome.prototype.standardsCompliance="50%";
awesome.prototype.init = function (){
// code
}
awesome.prototype.doStuff = function(){
// code
}
awesome.prototype.doMoreStuff = function(){
// code
}
add object instance or class definition to an existing namespace, class definition or object instance
namespace.awesome = ....
classDefinition.awesome = ...
objectInstance.awesome = ...
February 20th, 2006 at 12:09 am
February 20th, 2006 at 2:18 pm
I would rewrite the part below:
init:function(){
if(!document.getElementById('bla')){return;}
myStuff.myVariable=document.getElementById('bla');
alert(myStuff.myVariable.innerHTML);
}
like this (no need to search for 'bla' twice):
init:function(){
var oBla = document.getElementById('bla');
if (oBla==undefined) {return;}
myStuff.myVariable=oBla;
alert(myStuff.myVariable.innerHTML);
}
February 21st, 2006 at 3:06 pm
I like using Object Notation for most applications. However, in the past, I have favoured the following notation, perhaps due to its “evil genius” aura, usually to take advantage of private members.
var myObject = new function()
{
var privateVariable = "Hello";
this.publicVariable = "World!";
this.getPrivateVariable = function()
{
return privateVariable;
}
this.setPrivateVariable = function(newPrivateVariable)
{
privateVariable = newPrivateVariable;
}
}
alert(myObject.privateVariable + " " + myObject.publicVariable); // undefined World!
alert(myObject.getPrivateVariable() + " " + myObject.publicVariable); // Hello World!
myObject.privateVariable = "Goodbye, Cruel";
alert(myObject.privateVariable + " " + myObject.publicVariable); // Goodbye, Cruel World!
alert(myObject.getPrivateVariable() + " " + myObject.publicVariable); // Hello World!
This is a nice way of achieving encapsulation, as the example shows. It’s not possible to use the private variables directly, the get and set methods must be used.
I’ve not seen any equivalent examples using object notation though, can it be done? I’d love to become 100% converted!
February 21st, 2006 at 4:53 pm
Good article Chris. I had noticed the same trend that you did while watching all the Ajax stuff pour in. I had begun using it a little bit (and used it more when you suggested it for my latest problem via thelist - hat tip to you) and I'm finding not only is it clean and sensible, but I like reading it better than the old way - it just seems to make more sense.
Looks like lots of these new Ajax frameworks and Libs are using it too.
February 23rd, 2006 at 7:55 pm
April 19th, 2006 at 2:55 pm
I tend to use this method to create object with attributes and methods. I'm not too fond of Object Literal style, since I feel this has a more clean feel, and makes it easy to change underlying methods, without having to cut and paste source all over the place. But my biggest issue with Object Literals is the fact you need that little comma, so ugly! (not to mention har d to spot)
/* Object constructor */
function BioQuery( inputQuery ) {
/* properties */
this.queryString;
this.queryXML;
/* methods */
this.tokenizer = _BioQuery_tokenizer;
this.toTree = _BioQuery_toTree;
this.toXML = _BioQuery_toXML;
}
/* implementation of the methods */
function _BioQuery_tokenizer() {}
function _BioQuery_toTree() {}
function _BioQuery_toXML() {}
/* Init object instance */
var bq = new BioQuery('test');
May 10th, 2006 at 7:04 am
Your Replies No comments have been made. [...]
May 14th, 2006 at 10:13 pm
May 24th, 2006 at 9:21 am
May 25th, 2006 at 10:54 am
May 27th, 2006 at 1:21 am
May 27th, 2006 at 2:35 am
This post really got me thinking. I work with Flash, and ActionScript is basically the same language as JavaScript, so it, too, has the object literal. Not to link-whore, but I've written a post myself on how pretty much this exact same use of the object literal would really clear up a lot of code I've seen.
May 31st, 2006 at 11:16 am
Check out Ajile. It’s an excellent approach to namespaces (code organization) in JavaScript.
June 12th, 2006 at 7:32 pm
June 13th, 2006 at 10:23 am
July 17th, 2006 at 3:52 pm
July 17th, 2006 at 5:52 pm
July 20th, 2006 at 4:25 pm
Hi Chris, awesome article. But i am having issues with object scope i think.
MyObject = {
objectProperty:"HELLO",
applyAction : function(item) {
item.onmouseover = this.doOver;
},
doOver : function() {
alert(objectProperty);
}
}
all i get in alert window is "undefined". How can i make javscript to alert objectProperty without assigning objectProperty to a global variable?
Answer: alert(MyObject.objectProperty);
July 20th, 2006 at 4:59 pm
thanks, but what if i have 2 instances of that object at the same time?
August 12th, 2006 at 4:10 pm
August 12th, 2006 at 7:49 pm
November 11th, 2006 at 8:49 pm
Bit late but in case anyone has the same thing as Merth, the line you’ll need is:
Answer: alert(<em>this</em>.objectProperty);
That’ll reference the current instance of the object in case you’ve got multiples.
December 7th, 2006 at 3:38 pm
I recently stumbled upon some usage of Object Literals and found your site while trying to learn why. I still don't understand why object literals are better than using prototype.