Another discussion born from a question at stackoverflow. Today I’m laying out the differences between object literals and constructed objects, when to use which, how to get the most out of them, and a few other tricks along the way. Let’s get started.

Object Literals / Static Objects

Object literals, or static objects, don’t require instantiation with the new operator and also behave like singletons. They are often used for providing utility classes since methods can be called statically, or as parameter packages to provide named arguments or lists to other functions. Consider the following example that illustrates this singleton property of object literals:

Example 1: Static object singleton behavior

1

2

3

4

5

6

7

8

varstaticObject1={

a:123,

b:456

};

varstaticObject2=staticObject1;

staticObject2.b="hats";

console.log(staticObject1,staticObject2);

Output:

1

2

Objecta=123b=456Objecta=123b=456

Objecta=123b=hats Objecta=123b=hats

Notice that changing staticObject1.b also affected staticObject2.b. This happens because in JavaScript, when you assign an object to another variable, it simply creates a reference.

The singleton behavior may not always be the desired effect. Many libraries, such as Dojo, offer an object cloning method that can avoid this behavior if just you want to make a copy of a static object. Continuing the previous example, consider the following:

Example 2: Circumventing the singleton behavior

1

2

3

varstaticObject3=dojo.clone(staticObject1);// See the documentation in the link above

staticObject1.a="pants";

console.log(staticObject1,staticObject2,staticObject3);

Output:

1

Objecta=pantsb=hats Objecta=pantsb=hats Objecta=123b=hats

Notice that the values of the members of staticObject1 and staticObject2 are the same, whereas staticObject3 is not affected by changes to these other objects.

Static objects are also useful for creating project or library namespaces, rather than filling up the global scope, and promote compatibility like no one’s business. This is useful when creating libraries that require portability or interoperability. This can be seen in popular libraries such as Dojo, YUI, ExtJs, and others where all or most methods are called within that library’s specific context (e.g.: dojo.examplMethod(), YUI().exampleMethod(), and Ext.exampleMethod() respectively).

One thing to remember is that in object literals, all members and methods are necessarily public. Forever and always, so help me Douglas Crockford. However, this is not the case for constructed objects, as you’ll see shortly. Access restrictions notwithstanding, static objects can also be considered loosely analogous in purpose and use to C/C++'s struct type.

Constructed Objects / Instantiated Objects

Classes in JavaScript are based on prototypal inheritance, which can be a lengthy subject in itself and can be read about here, here, and here. For now, we will just compare the differences between instantiated and static objects and leave inheritance for another day.

As opposed to static objects, this method of object creation gives the unique opportunity for private scope object members and methods thanks to JavaScript’s closure property. Consider the following example of private class members:

Notice that typeof o.privateMember is “undefined” and not accessible outside of the object, but is from within.

Private methods can also be defined. They are not as straight forward but are still simple to implement. The issue lies in that the value of this within a private method will refer to window if you try to execute it as if it were just any method. There are at least three techniques that can be applied to ensure that this refers to the object that we are working within, in this case, the instance of SomeObject. Consider the following example:

Notice that within privateMethodWrapper(), privatemethod was executed using call and passing in this for the function’s context. This is all fine and allows us to use this within the private method as we normally would; however, the following technique is slightly more preferable as it simplifies the calling context. The previous example can be rearranged to the following:

Notice that a new private member, self, was introduced and provides a reference to this within privateMethod via the closure property. This method is agreeable for most situations; however, my syntax highlighter doesn’t highlight self the same as it does this, so I prefer the following method.

The third method effectively “locks in” the value of this within the private method. It is the most preferable in that it allows you to have a normal definition using this with the private method as in example #4, and a clean calling context as in example #5. Both the Dojo and Prototype libraries offer utility methods to do this for us: dojo.hitch and function.prototype.bind respectively. I will show how to use these methods, as well as how write your own utility method for achieving the same results for those of you not using those libraries.

As you can see, all four of these context locking methods (examples #6 – #9) allow you to keep the executing scope of your private method clean, freeing you to write the body of your private method as you would any other, and removes the superfluous <tt>self</tt> reference. I’ll let you decide which method works best for you, but I think the prototypal approach is the cleanest. For more information on how context locking works, see the MDC references for apply and call.

Wrapping it Up

There are definite roles that static and instantiated objects fill. For me, part of the joy of writing in JavaScript is knowing when to use which, and how to get the most milage out of their differences. What about you? Let me know if you have any preferences or guidelines when it comes to creating and using objects in JavaScript.