homepage Welcome to WebmasterWorld Guest from 54.196.168.78
register, free tools, login, search, subscribe, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
Forum Library, Charter, Moderator: open

JavaScript and AJAX Forum

    
Why I Think Object Literal Notation is Not So Great
(In Most Cases)
Fotiman




msg:3066164
 5:14 pm on Aug 30, 2006 (gmt 0)

Recently, I've seen a substantial increase in Object Literal notation being used. For those not familiar with this format, it's a method for creating "objects" using name/value pairs, and it looks something like this:


var circle = { x : 0, y : 0, radius: 2 };

or


var obj = {
a : Object,
b : Array,
c : false,
d : null,
init : function() {
// set local object vars here
this.run();
},
run : function() {
// run bulk of behavior here
}
}
// This object would be instanciated by calling:
obj.init();

Another example might look like this:


var myNamespace = function() {
var private_var;
function private_method() {
// do stuff here
}
return {
method_1 : function() {
// do stuff here
},
method_2 : function() {
// do stuff here
}
};
}();

The above example creates a "namespace" for your JavaScript to prevent your global variables from conflicting with those of 3rd party scripts. In this example, you have 1 global variable, myNamespace, which you then define public methods in. With the example above, you might call:


myNamespace.method_1();
myNamespace.method_2();

Anyhow, I've seen the Object Literal method being used to define objects in a lot of the newer JavaScript libraries available. But this looks extremely inefficient to me, when compared to more traditional approaches. With this method, each instance of an object contains a copy of all of the methods and properties of that object, a waste of memory if you ask me. However, using prototypes allows a single instance of a method to be shared by all instances of a "class" (note, JavaScript does not really have classes in the sense that C++ and Java do, but prototype inheritance is close enough that I'm going to refer to them in the same sense). For example:

Object Literal


function Obj( prop1, prop2 ) {
return {
p1 : prop1,
p2 : prop2,
greet : function(){alert(this.p1);},
getP2 : function(){return this.p2;}
};
}

vs.

Prototype


function Obj( prop1, prop2 ) {
this.p1 = prop1;
this.p2 = prop2;
}
Obj.prototype.greet = function(){alert(this.p1);};
Obj.prototype.getP2 = function(){return this.p2;};

With both of these methods, I can create instances of Obj like this:


var man = new Obj( "hello", "world" );
var world = new Obj( "hello", "man" );

With the Object Literal method, if I'm passing around an instance of Obj, it includes a copy of the functions greet and getP2 (in this case, it's only a little over 50 Bytes for those functions). With the prototype method, these functions are still available, but they don't get copied with the instance of the object. 50 bytes is not a huge amount. But when you have more complex methods, that can add up quickly, particularly if you're creating many instances.

With all that said, I do think there is one particularly good place to use Object Literal Notation. It's the namespace example I listed above (credits to Dustin Diaz). However, I would define it such that there is only 1 method (init) which basically creates all of your object instances (with the "classes" for those objects defined using the prototype method), and assigns all your page behaviors.


<script type="text/javascript" src="Obj.js"></script>
<script type="text/javascript">
var myNamespace = function() {
return {
init : function() {
// Create instances of my prototyped objects here
// and assign all behaviors here
var man = new Obj( "hello", "world" );
man.greet();
var world = new Obj( "hello", "man" );
world.greet();
}
}
}();
</script>

myNamespace.init would then be called on the window onload event.

I look forward to hearing other opinions on this.

Notes:
Object Literal Notation has gained popularity thanks to JSON (JavaScript Object Notation) [json.org]. JSON is a lightweight data-interchange format. It seems to be a subset of Object Literal notation. It's essentially the same, but with slightly more strict requirements (names must be quoted for example).

Some examples above as given by Dustin Diaz on his blog for "Namspacing your JavaScript" and "JSON for the masses" (both good reads). :-)

[edited by: Fotiman at 5:16 pm (utc) on Aug. 30, 2006]

 

daveVk




msg:3066754
 1:44 am on Aug 31, 2006 (gmt 0)

Not being familiar with prototypes I whould have written

function Obj( prop1, prop2 ) {
this.p1 = prop1;
this.p2 = prop2;
this.greet = function(){alert(this.p1);};
this.getP2 = function(){return this.p2;};
}

Which is assumeably is about as efficient as your Object Literal example

Is your point to use prototypes to save storage and time, is am I missing something?

Fotiman




msg:3066772
 2:13 am on Aug 31, 2006 (gmt 0)


Not being familiar with prototypes I whould have written

function Obj( prop1, prop2 ) {
this.p1 = prop1;
this.p2 = prop2;
this.greet = function(){alert(this.p1);};
this.getP2 = function(){return this.p2;};
}

Which is assumeably is about as efficient as your Object Literal example

Yes, that is as "in"efficient as the Object Literal example. This creates a copy of the function for every instance. So for example, if I was to do this:

var o1 = new Obj( "a","b" );
var o2 = new Obj( "a","b" );
var o3 = new Obj( "a","b" );
var o4 = new Obj( "a","b" );
var o5 = new Obj( "a","b" );

I've just created 5 copies of those functions, which is inefficient because those functions don't ever change. Instead, if you use the prototype object to define those functions, then in the example above those methods are not "inside" the object, but they are still accessible to the object. It's basically how JavaScript does inheritance.


Is your point to use prototypes to save storage and time, is am I missing something?

To save on memory usage, which could also impact performance. Take this example:


function myHonkingClass( idRef )
{
this.myId = idRef;
this.doSomething1=function(){...};
this.doSomething2=function(){...};
this.doSomething3=function(){...};
this.doSomething4=function(){...};
this.doSomething5=function(){...};
this.doSomething6=function(){...};
this.doSomething7=function(){...};
this.doSomething8=function(){...};
this.doSomething9=function(){...};
}

Now imagine that each of those functions contains a considerable amount of code. If I create 5 objects of this "class", I'm creating 5 copies of all those functions in memory, which could slow things down. Now consider the alternative:


function myHonkingClass( idRef )
{
this.myId = idRef;
}
myHonkingClass.prototype.doSomething1=function(){...};
myHonkingClass.prototype.doSomething2=function(){...};
myHonkingClass.prototype.doSomething3=function(){...};
myHonkingClass.prototype.doSomething4=function(){...};
myHonkingClass.prototype.doSomething5=function(){...};
myHonkingClass.prototype.doSomething6=function(){...};
myHonkingClass.prototype.doSomething7=function(){...};
myHonkingClass.prototype.doSomething8=function(){...};
myHonkingClass.prototype.doSomething9=function(){...};

With this design, there is only a single instance of all those functions. I still access them the same way:

var myObj = new myHonkingClass('someId');
myObj.doSomething1();

But it's much more efficient.

Hope that clears it up some. If you have access to the O'Reilly book "JavaScript: The Definitive Guide", there's a good section on prototypes in there.

Also, this is not to be confused with the prototype JavaScript library [prototype.conio.net], which is a JavaScript framework.

daveVk




msg:3066828
 3:27 am on Aug 31, 2006 (gmt 0)

Thanks I take your point, will read up on prototypes.

daveVk




msg:3067030
 7:58 am on Aug 31, 2006 (gmt 0)

So when the following is interpreted

myObj.doSomething1();

Either the doSomething1 property(method) of myObj is called
Or if that is undefined, the prototype doSomething1 property from the constructor function.

So prototype can be used as a means of defaulting, or where a single value is applicable to all instances of a particular class.

Assumably all functions have a prototype object as a property, whether intended to be used for class construction ( called with new prefix ) or not.

Fotiman




msg:3067529
 3:56 pm on Aug 31, 2006 (gmt 0)


So when the following is interpreted

myObj.doSomething1();

Either the doSomething1 property(method) of myObj is called
Or if that is undefined, the prototype doSomething1 property from the constructor function.

Correct.


So prototype can be used as a means of defaulting, or where a single value is applicable to all instances of a particular class.

Correct.


Assumably all functions have a prototype object as a property, whether intended to be used for class construction ( called with new prefix ) or not.

Not correct.

Every object has a prototype, and an object inherits the properties of its prototype. It doesn't make sense for a function to have a prototype.

daveVk




msg:3068296
 1:28 am on Sep 1, 2006 (gmt 0)

Perhaps I stated the last point badly "All functions have a property named 'prototype' " whould be more precise.

A statement like

myHonkingClass.prototype.doSomething1=function(){...};

where myHonkingClass is a function (constructer) seems to be consistent with this assertion. Or is there some syntax rule, like "prototype" is a reserved word or myHonkingClass.abc does not refer to property abc of myHonkingClass becouse functions are not proper objects.

Sorry if getting to far off topic. Thanks again.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved